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 #define RANGE4(a,b,c,d) RANGE(a) RANGE(b) RANGE(c) RANGE(d)
17 #define REVERSE_BYTES_32(x) ((((x)&0xff)<<24) | (((x)&0xff00)<<8) | (((x)&0xff0000)>>8) | (((x)&0xff000000)>>24))
18 #define REVERSE_BYTES_24(x) ((((x)&0xff)<<16) | ((x)&0xff00) | (((x)&0xff0000)>>8))
19 #define REVERSE_BYTES_16(x) ((((x)&0xff)<<8 ) | (((x)&0xff00)>>8))
20
21 #define COLOR_R16(x) (((x)>>8)&0xFF00)
22 #define COLOR_G16(x) ((x)&0xFF00)
23 #define COLOR_B16(x) (((x)<<8)&0xFF00)
24
25 static int rop_map[] = {
26 GXcopy /* ropCopyPut */, /* dest = src */
27 GXxor /* ropXorPut */, /* dest ^= src */
28 GXand /* ropAndPut */, /* dest &= src */
29 GXor /* ropOrPut */, /* dest |= src */
30 GXcopyInverted /* ropNotPut */, /* dest = !src */
31 GXinvert /* ropInvert */, /* dest = !dest */
32 GXclear /* ropBlackness */, /* dest = 0 */
33 GXandReverse /* ropNotDestAnd */, /* dest = (!dest) & src */
34 GXorReverse /* ropNotDestOr */, /* dest = (!dest) | src */
35 GXset /* ropWhiteness */, /* dest = 1 */
36 GXandInverted /* ropNotSrcAnd */, /* dest &= !src */
37 GXorInverted /* ropNotSrcOr */, /* dest |= !src */
38 GXequiv /* ropNotXor */, /* dest ^= !src */
39 GXnand /* ropNotAnd */, /* dest = !(src & dest) */
40 GXnor /* ropNotOr */, /* dest = !(src | dest) */
41 GXnoop /* ropNoOper */ /* dest = dest */
42 };
43
44 int
prima_rop_map(int rop)45 prima_rop_map( int rop)
46 {
47 if ( rop < 0 || rop >= sizeof( rop_map)/sizeof(int))
48 return GXnoop;
49 else
50 return rop_map[ rop];
51 }
52
53 void
prima_get_gc(PDrawableSysData selfxx)54 prima_get_gc( PDrawableSysData selfxx)
55 {
56 XGCValues gcv;
57 Bool bitmap, layered;
58 struct gc_head *gc_pool;
59
60 if ( XX-> gc && XX-> gcl) return;
61
62 if ( XX-> gc || XX-> gcl) {
63 warn( "UAG_010: internal error");
64 return;
65 }
66
67 bitmap = XT_IS_BITMAP(XX) ? true : false;
68 layered = XF_LAYERED(XX) ? true : false;
69 gc_pool = bitmap ? &guts.bitmap_gc_pool : ( layered ? &guts.argb_gc_pool : &guts.screen_gc_pool );
70 XX->gcl = TAILQ_FIRST(gc_pool);
71 if (XX->gcl)
72 TAILQ_REMOVE(gc_pool, XX->gcl, gc_link);
73 if (!XX->gcl) {
74 gcv. graphics_exposures = false;
75 XX-> gc = XCreateGC( DISP, (bitmap || layered) ? XX-> gdrawable : guts. root, GCGraphicsExposures, &gcv);
76 XCHECKPOINT;
77 if (( XX->gcl = alloc1z( GCList)))
78 XX->gcl->gc = XX-> gc;
79 }
80 if ( XX-> gcl) XX->gc = XX->gcl->gc;
81 }
82
83 void
prima_release_gc(PDrawableSysData selfxx)84 prima_release_gc( PDrawableSysData selfxx)
85 {
86 Bool bitmap, layered;
87 struct gc_head *gc_pool;
88
89 if ( XX-> gc) {
90 if ( XX-> gcl == NULL)
91 warn( "UAG_011: internal error");
92 bitmap = XT_IS_BITMAP(XX) ? true : false;
93 layered = XF_LAYERED(XX) ? true : false;
94 gc_pool = bitmap ? &guts.bitmap_gc_pool : ( layered ? &guts.argb_gc_pool : &guts.screen_gc_pool );
95 if ( XX-> gcl)
96 TAILQ_INSERT_HEAD(gc_pool, XX->gcl, gc_link);
97 XX->gcl = NULL;
98 XX->gc = NULL;
99 } else {
100 if ( XX-> gcl) {
101 warn( "UAG_012: internal error");
102 return;
103 }
104 }
105 }
106
107 /*
108 macros to multiply line pattern entries to line width in
109 a more-less aestethic fashion :-)
110 */
111 #define MAX_DASH_LEN 2048
112 #define dDASH_FIX(line_width,source,length) \
113 int df_i, df_lw = line_width + .5, df_len = length; \
114 char df_list[MAX_DASH_LEN], *df_src = (char*)source, *df_dst = df_list
115 #define DASH_FIX \
116 if ( df_lw > 1) {\
117 int on = 0;\
118 if ( df_len > MAX_DASH_LEN) df_len = MAX_DASH_LEN;\
119 for ( df_i = 0; df_i < df_len; df_i++) {\
120 unsigned int w = *((unsigned char*)df_src++);\
121 if (( on = !on)) {\
122 if ( w > 1) w *= df_lw;\
123 } else {\
124 w = w * df_lw + 1;\
125 }\
126 if ( w > 255) w = 255;\
127 *((unsigned char*)df_dst++) = w;\
128 }\
129 df_src = df_list;\
130 }
131 #define DASHES df_src, df_len
132
133 void
prima_prepare_drawable_for_painting(Handle self,Bool inside_on_paint)134 prima_prepare_drawable_for_painting( Handle self, Bool inside_on_paint)
135 {
136 DEFXX;
137 unsigned long mask = VIRGIN_GC_MASK;
138 int w, h;
139 XRectangle r;
140
141 XF_IN_PAINT(XX) = true;
142 XX-> btransform. x = XX-> btransform. y = 0;
143 XX-> gcv. ts_x_origin = XX-> gcv. ts_y_origin = 0;
144 if ( inside_on_paint && XX-> udrawable && is_opt( optBuffered) && !is_opt( optInDrawInfo) ) {
145 if ( XX-> invalid_region) {
146 XClipBox( XX-> invalid_region, &r);
147 XX-> bsize. x = w = r. width;
148 XX-> bsize. y = h = r. height;
149 XX-> btransform. x = - r. x;
150 XX-> btransform. y = r. y;
151 } else {
152 r. x = r. y = 0;
153 XX-> bsize. x = w = XX-> size. x;
154 XX-> bsize. y = h = XX-> size. y;
155 }
156 if ( w <= 0 || h <= 0) goto Unbuffered;
157 XX-> gdrawable = XCreatePixmap( DISP, XX-> udrawable, w, h, XX->visual->depth);
158 XCHECKPOINT;
159 if (!XX-> gdrawable) goto Unbuffered;
160 XX-> gcv. ts_x_origin = -r.x;
161 XX-> gcv. ts_y_origin = -r.y;
162 } else if ( XX-> udrawable && !XX-> gdrawable) {
163 Unbuffered:
164 XX-> gdrawable = XX-> udrawable;
165 }
166
167 XX-> paint_rop = XX-> rop;
168 XX-> paint_rop2 = XX-> rop2;
169 XX-> paint_alpha = XX-> alpha;
170 XX-> paint_line_width = XX-> line_width;
171 XX-> flags. paint_base_line = XX-> flags. base_line;
172 XX-> flags. paint_opaque = XX-> flags. opaque;
173 XX-> saved_font = PDrawable( self)-> font;
174 XX-> gcv. clip_mask = None;
175 XX-> gtransform = XX-> transform;
176 XX-> fill_mode = XX->saved_fill_mode;
177
178 prima_get_gc( XX);
179 XX-> gcv. subwindow_mode = (XX->flags.clip_by_children ? ClipByChildren : IncludeInferiors);
180
181 XChangeGC( DISP, XX-> gc, mask, &XX-> gcv);
182 XCHECKPOINT;
183
184 if ( XX-> dashes) {
185 dDASH_FIX( XX-> paint_line_width, XX-> dashes, XX-> ndashes);
186 DASH_FIX;
187 XSetDashes( DISP, XX-> gc, 0, DASHES);
188 XX-> paint_ndashes = XX-> ndashes;
189 if (( XX-> paint_dashes = malloc( XX-> ndashes)))
190 memcpy( XX-> paint_dashes, XX-> dashes, XX-> ndashes);
191 XX-> line_style = ( XX-> paint_rop2 == ropCopyPut) ? LineDoubleDash : LineOnOffDash;
192 } else {
193 XX-> paint_dashes = malloc(1);
194 if ( XX-> ndashes < 0) {
195 XX-> paint_dashes[0] = '\0';
196 XX-> paint_ndashes = 0;
197 } else {
198 XX-> paint_dashes[0] = '\1';
199 XX-> paint_ndashes = 1;
200 }
201 XX-> line_style = LineSolid;
202 }
203
204 XX-> clip_rect. x = 0;
205 XX-> clip_rect. y = 0;
206 XX-> clip_rect. width = XX-> size.x;
207 XX-> clip_rect. height = XX-> size.y;
208 if ( XX-> invalid_region && inside_on_paint && !is_opt( optInDrawInfo)) {
209 if ( XX-> flags. kill_current_region) {
210 XDestroyRegion( XX-> current_region);
211 XX-> flags. kill_current_region = 0;
212 }
213 if ( XX-> btransform. x != 0 || XX-> btransform. y != 0) {
214 Region r = XCreateRegion();
215 XUnionRegion( r, XX-> invalid_region, r);
216 XOffsetRegion( r, XX-> btransform. x, -XX-> btransform. y);
217 XSetRegion( DISP, XX-> gc, r);
218 XX-> current_region = r;
219 XX-> flags. kill_current_region = 1;
220 } else {
221 XSetRegion( DISP, XX-> gc, XX-> invalid_region);
222 XX-> current_region = XX-> invalid_region;
223 XX-> flags. kill_current_region = 0;
224 }
225 XX-> paint_region = XX-> invalid_region;
226 XX-> invalid_region = NULL;
227 }
228 XX-> clip_mask_extent. x = XX-> clip_mask_extent. y = 0;
229 XX-> flags. xft_clip = 0;
230
231 apc_gp_set_antialias( self, XX-> flags.saved_antialias);
232 apc_gp_set_color( self, XX-> saved_fore);
233 apc_gp_set_back_color( self, XX-> saved_back);
234 memcpy( XX-> saved_fill_pattern, XX-> fill_pattern, sizeof( FillPattern));
235 XX-> fill_pattern[0]++; /* force */
236 apc_gp_set_fill_pattern( self, XX-> saved_fill_pattern);
237 XX-> saved_fill_pattern_offset = XX-> fill_pattern_offset;
238 apc_gp_set_fill_pattern_offset( self, XX-> saved_fill_pattern_offset);
239
240 if ( !XX-> flags. reload_font && XX-> font && XX-> font-> id) {
241 XSetFont( DISP, XX-> gc, XX-> font-> id);
242 XCHECKPOINT;
243 } else {
244 apc_gp_set_font( self, &PDrawable( self)-> font);
245 XX-> flags. reload_font = false;
246 }
247 }
248
249 void
prima_cleanup_drawable_after_painting(Handle self)250 prima_cleanup_drawable_after_painting( Handle self)
251 {
252 DEFXX;
253 DELETE_ARGB_PICTURE(XX->argb_picture);
254 #ifdef USE_XFT
255 prima_xft_gp_destroy( self );
256 #endif
257 if ( XX-> flags. kill_current_region) {
258 XDestroyRegion( XX-> current_region);
259 XX-> flags. kill_current_region = 0;
260 }
261 XX-> current_region = 0;
262 XX-> flags. xft_clip = 0;
263 if ( XX-> udrawable && XX-> udrawable != XX-> gdrawable && XX-> gdrawable && !is_opt( optInDrawInfo)) {
264 if ( XX-> paint_region) {
265 XSetRegion( DISP, XX-> gc, XX-> paint_region);
266 } else {
267 Region region = XCreateRegion();
268 XRectangle r;
269 r. x = -XX-> btransform. x;
270 r. y = XX-> btransform. y;
271 r. width = XX->bsize.x;
272 r. height = XX->bsize.y;
273 XUnionRectWithRegion( &r, region, region);
274 XSetRegion( DISP, XX-> gc, region);
275 XDestroyRegion( region);
276 }
277 XCHECKPOINT;
278 XSetFunction( DISP, XX-> gc, GXcopy);
279 XCopyArea( DISP, XX-> gdrawable, XX-> udrawable, XX-> gc,
280 0, 0,
281 XX-> bsize.x, XX-> bsize.y,
282 -XX-> btransform. x, XX-> btransform. y);
283 XCHECKPOINT;
284 XFreePixmap( DISP, XX-> gdrawable);
285 XCHECKPOINT;
286 XX-> gdrawable = XX-> udrawable;
287 XX-> btransform. x = XX-> btransform. y = 0;
288 }
289 prima_release_gc(XX);
290 memcpy( XX-> fill_pattern, XX-> saved_fill_pattern, sizeof( FillPattern));
291 XX-> fill_pattern_offset = XX-> saved_fill_pattern_offset;
292 if ( XX-> font && ( --XX-> font-> refCnt <= 0)) {
293 prima_free_rotated_entry( XX-> font);
294 XX-> font-> refCnt = 0;
295 }
296 if ( XX-> paint_dashes) {
297 free(XX->paint_dashes);
298 XX-> paint_dashes = NULL;
299 }
300 XX-> paint_ndashes = 0;
301 XF_IN_PAINT(XX) = false;
302 PDrawable( self)-> font = XX-> saved_font;
303 if ( XX-> paint_region) {
304 XDestroyRegion( XX-> paint_region);
305 XX-> paint_region = NULL;
306 }
307 XFlush(DISP);
308 }
309
310 #define PURE_FOREGROUND if (!XX->flags.brush_fore) {\
311 XSetForeground( DISP, XX-> gc, XX-> fore. primary);\
312 XX->flags.brush_fore=1;\
313 }\
314 if (!XX->flags.brush_back && XX-> paint_rop2 == ropCopyPut) {\
315 XSetBackground( DISP, XX-> gc, XX-> back. primary);\
316 XX->flags.brush_back=1;\
317 }\
318 XSetFillStyle( DISP, XX-> gc, FillSolid);\
319
320 Bool
prima_make_brush(DrawableSysData * XX,int colorIndex)321 prima_make_brush( DrawableSysData * XX, int colorIndex)
322 {
323 Pixmap p;
324 if ( XT_IS_BITMAP(XX) || ( guts. idepth == 1)) {
325 int i;
326 FillPattern mix, *p1, *p2;
327 if ( colorIndex > 0) return false;
328 p1 = &guts. ditherPatterns[ 64 - (XX-> fore. primary ? 64 : XX-> fore. balance)];
329 p2 = &guts. ditherPatterns[ 64 - (XX-> back. primary ? 64 : XX-> back. balance)];
330 for ( i = 0; i < sizeof( FillPattern); i++)
331 mix[i] = ((*p1)[i] & XX-> fill_pattern[i]) | ((*p2)[i] & ~XX-> fill_pattern[i]);
332 XSetForeground( DISP, XX-> gc, 1);
333 XSetBackground( DISP, XX-> gc, 0);
334 XX-> flags. brush_fore = 0;
335 XX-> flags. brush_back = 0;
336 if (
337 ( memcmp( mix, fillPatterns[ fpSolid], sizeof( FillPattern)) != 0) &&
338 ( p = prima_get_hatch( &mix))
339 ) {
340 XSetStipple( DISP, XX-> gc, p);
341 XSetFillStyle( DISP, XX-> gc, FillOpaqueStippled);
342 } else
343 XSetFillStyle( DISP, XX-> gc, FillSolid);
344 } else if ( XX-> flags. brush_null_hatch) {
345 if ( colorIndex > 0) return false;
346 if ( XX-> fore. balance) {
347 p = prima_get_hatch( &guts. ditherPatterns[ XX-> fore. balance]);
348 if ( p) {
349 XSetStipple( DISP, XX-> gc, p);
350 XSetFillStyle( DISP, XX-> gc, FillOpaqueStippled);
351 XSetBackground( DISP, XX-> gc, XX-> fore. secondary);
352 XX-> flags. brush_back = 0;
353 } else /* failure */
354 XSetFillStyle( DISP, XX-> gc, FillSolid);
355 } else
356 XSetFillStyle( DISP, XX-> gc, FillSolid);
357 if (!XX->flags.brush_fore) {
358 XSetForeground( DISP, XX-> gc, XX-> fore. primary);
359 XX->flags.brush_fore = 1;
360 }
361 } else if ( XX->fore.balance == 0 && XX->back.balance == 0) {
362 if ( colorIndex > 0) return false;
363
364 p = prima_get_hatch( &XX-> fill_pattern);
365 XSetFillStyle( DISP, XX-> gc, p ? FillOpaqueStippled : FillSolid);
366 if ( p) XSetStipple( DISP, XX-> gc, p);
367 if (!XX->flags.brush_fore) {
368 XSetForeground( DISP, XX-> gc, XX-> fore. primary);
369 XX->flags.brush_fore = 1;
370 }
371 if (p && !XX->flags.brush_back) {
372 XSetBackground( DISP, XX-> gc, XX-> back. primary);
373 XX->flags.brush_back = 1;
374 }
375 } else {
376 switch ( colorIndex) {
377 case 0: /* back mix */
378 if ( XX-> back. balance) {
379 p = prima_get_hatch( &guts. ditherPatterns[ XX-> back. balance]);
380 if ( p) {
381 XSetStipple( DISP, XX-> gc, p);
382 XSetFillStyle( DISP, XX-> gc, FillOpaqueStippled);
383 XSetBackground( DISP, XX-> gc, XX-> back. secondary);
384 } else /* failure */
385 XSetFillStyle( DISP, XX-> gc, FillSolid);
386 } else
387 XSetFillStyle( DISP, XX-> gc, FillSolid);
388 XSetForeground( DISP, XX-> gc, XX-> back. primary);
389 XX-> flags. brush_back = 0;
390 break;
391 case 1: /* fore mix */
392 if ( memcmp( XX-> fill_pattern, fillPatterns[fpEmpty], sizeof(FillPattern))==0)
393 return false;
394 if ( XX-> fore. balance) {
395 int i;
396 FillPattern fp;
397 memcpy( &fp, &guts. ditherPatterns[ XX-> fore. balance], sizeof(FillPattern));
398 for ( i = 0; i < 8; i++)
399 fp[i] &= XX-> fill_pattern[i];
400 p = prima_get_hatch( &fp);
401 } else
402 p = prima_get_hatch( &XX-> fill_pattern);
403 if ( !p) return false;
404 XSetStipple( DISP, XX-> gc, p);
405 XSetFillStyle( DISP, XX-> gc, FillStippled);
406 if ( !XX-> flags. brush_fore) {
407 XSetForeground( DISP, XX-> gc, XX-> fore. primary);
408 XX-> flags. brush_fore = 1;
409 }
410 break;
411 case 2: /* fore mix with fill pattern */
412 if ( memcmp( XX-> fill_pattern, fillPatterns[fpEmpty], sizeof(FillPattern))==0)
413 return false;
414 if ( XX-> fore. balance ) {
415 int i;
416 FillPattern fp;
417 memcpy( &fp, &guts. ditherPatterns[ XX-> fore. balance], sizeof(FillPattern));
418 for ( i = 0; i < 8; i++)
419 fp[i] = (~fp[i]) & XX-> fill_pattern[i];
420 p = prima_get_hatch( &fp);
421 if ( !p) return false;
422 XSetStipple( DISP, XX-> gc, p);
423 XSetFillStyle( DISP, XX-> gc, FillStippled);
424 XSetForeground( DISP, XX-> gc, XX-> fore. secondary);
425 XX-> flags. brush_fore = 0;
426 break;
427 } else
428 return false;
429 default:
430 return false;
431 }
432 }
433 return true;
434 }
435
436 Bool
apc_gp_init(Handle self)437 apc_gp_init( Handle self)
438 {
439 if ( guts. dynamicColors && !prima_palette_alloc( self)) return false;
440 return true;
441 }
442
443 Bool
apc_gp_done(Handle self)444 apc_gp_done( Handle self)
445 {
446 DEFXX;
447 if (!XX) return false;
448 if ( XX-> dashes) {
449 free(XX-> dashes);
450 XX-> dashes = NULL;
451 }
452 XX-> ndashes = 0;
453 if ( guts. dynamicColors) {
454 prima_palette_free( self, true);
455 free(XX-> palette);
456 }
457 prima_release_gc(XX);
458 return true;
459 }
460
461 static int
arc_completion(double * angleStart,double * angleEnd,int * needFigure)462 arc_completion( double * angleStart, double * angleEnd, int * needFigure)
463 {
464 int max;
465 long diff = (long)( fabs( *angleEnd - *angleStart) * 64 + 0.5);
466
467 if ( diff == 0) {
468 *needFigure = false;
469 return 0;
470 }
471 diff /= 64;
472
473 while ( *angleStart > *angleEnd)
474 *angleEnd += 360;
475
476 while ( *angleStart < 0) {
477 *angleStart += 360;
478 *angleEnd += 360;
479 }
480
481 while ( *angleStart >= 360) {
482 *angleStart -= 360;
483 *angleEnd -= 360;
484 }
485
486 while ( *angleEnd >= *angleStart + 360)
487 *angleEnd -= 360;
488
489 if ( diff < 360) {
490 *needFigure = true;
491 return 0;
492 }
493
494 max = (int)(diff / 360);
495 *needFigure = ( max * 360) != diff;
496 return ( max % 2) ? 1 : 2;
497 }
498
499 static void
calculate_ellipse_divergence(void)500 calculate_ellipse_divergence(void)
501 {
502 static Bool init = false;
503 if ( !init) {
504 XGCValues gcv;
505 Pixmap px = XCreatePixmap( DISP, guts.root, 4, 4, 1);
506 GC gc = XCreateGC( DISP, px, 0, &gcv);
507 XImage *xi;
508 XSetForeground( DISP, gc, 0);
509 XFillRectangle( DISP, px, gc, 0, 0, 5, 5);
510 XSetForeground( DISP, gc, 1);
511 XDrawArc( DISP, px, gc, 0, 0, 4, 4, 0, 360 * 64);
512 if (( xi = XGetImage( DISP, px, 0, 0, 4, 4, 1, XYPixmap))) {
513 int i;
514 Byte *data[4];
515 if ( xi-> bitmap_bit_order == LSBFirst)
516 prima_mirror_bytes(( Byte*) xi-> data, xi-> bytes_per_line * 4);
517 for ( i = 0; i < 4; i++) data[i] = (Byte*)xi-> data + i * xi-> bytes_per_line;
518 #define PIX(x,y) ((data[y][0] & (0x80>>(x)))!=0)
519 if ( PIX(2,1) && !PIX(3,1)) guts. ellipseDivergence.x = -1; else
520 if ( !PIX(2,1) && !PIX(3,1)) guts. ellipseDivergence.x = 1;
521 if ( PIX(1,2) && !PIX(1,3)) guts. ellipseDivergence.y = -1; else
522 if ( !PIX(1,2) && !PIX(1,3)) guts. ellipseDivergence.y = 1;
523 #undef PIX
524 XDestroyImage( xi);
525 }
526 XFreeGC( DISP, gc);
527 XFreePixmap( DISP, px);
528 init = true;
529 }
530 }
531
532 #define ELLIPSE_RECT x - ( dX + 1) / 2 + 1, y - dY / 2, dX-guts.ellipseDivergence.x, dY-guts.ellipseDivergence.y
533 #define FILL_ANTIDEFECT_REPAIRABLE (((XX->fill_mode & fmOverlay) != 0) && \
534 ( rop_map[XX-> paint_rop] == GXcopy ||\
535 rop_map[XX-> paint_rop] == GXset ||\
536 rop_map[XX-> paint_rop] == GXclear))
537 #define FILL_ANTIDEFECT_OPEN {\
538 XGCValues gcv;\
539 gcv. line_width = 1;\
540 gcv. line_style = LineSolid;\
541 XChangeGC( DISP, XX-> gc, GCLineWidth, &gcv);\
542 }
543 #define FILL_ANTIDEFECT_CLOSE {\
544 XGCValues gcv;\
545 gcv. line_width = XX-> paint_line_width + .5;\
546 XChangeGC( DISP, XX-> gc, GCLineWidth, &gcv);\
547 }
548
549 Bool
apc_gp_arc(Handle self,int x,int y,int dX,int dY,double angleStart,double angleEnd)550 apc_gp_arc( Handle self, int x, int y, int dX, int dY, double angleStart, double angleEnd)
551 {
552 DEFXX;
553 int compl, needf;
554
555 if ( PObject( self)-> options. optInDrawInfo) return false;
556 if ( !XF_IN_PAINT(XX)) return false;
557 if ( dX <= 0 || dY <= 0) return false;
558 RANGE4(x, y, dX, dY);
559
560 SHIFT( x, y);
561 y = REVERT( y);
562 PURE_FOREGROUND;
563 calculate_ellipse_divergence();
564 compl = arc_completion( &angleStart, &angleEnd, &needf);
565 while ( compl--)
566 XDrawArc( DISP, XX-> gdrawable, XX-> gc, ELLIPSE_RECT, 0, 360 * 64);
567 if ( needf)
568 XDrawArc( DISP, XX-> gdrawable, XX-> gc, ELLIPSE_RECT,
569 angleStart * 64, ( angleEnd - angleStart) * 64);
570 XFLUSH;
571 return true;
572 }
573
574 Bool
apc_gp_bar(Handle self,int x1,int y1,int x2,int y2)575 apc_gp_bar( Handle self, int x1, int y1, int x2, int y2)
576 {
577 DEFXX;
578 int mix = 0;
579
580 if ( PObject( self)-> options. optInDrawInfo) return false;
581 if ( !XF_IN_PAINT(XX)) return false;
582
583 SHIFT( x1, y1); SHIFT( x2, y2);
584 SORT( x1, x2); SORT( y1, y2);
585 RANGE4( x1, y1, x2, y2);
586 while ( prima_make_brush( XX, mix++))
587 XFillRectangle( DISP, XX-> gdrawable, XX-> gc, x1, REVERT( y2), x2 - x1 + 1, y2 - y1 + 1);
588 XCHECKPOINT;
589 XFLUSH;
590 return true;
591 }
592
593 Bool
apc_gp_bars(Handle self,int nr,Rect * rr)594 apc_gp_bars( Handle self, int nr, Rect *rr)
595 {
596 DEFXX;
597 XRectangle *r, *rp;
598 int i, mix = 0;
599
600 if ( PObject( self)-> options. optInDrawInfo) return false;
601 if ( !XF_IN_PAINT(XX)) return false;
602 if ((r = malloc( sizeof( XRectangle)*nr)) == NULL) return false;
603
604 for ( i = 0, rp = r; i < nr; i++, rr++, rp++) {
605 SHIFT( rr->left,rr-> bottom); SHIFT( rr->right, rr->top);
606 SORT( rr->left, rr->right); SORT( rr->bottom, rr->top);
607 RANGE4( rr->left, rr->bottom, rr->right, rr->top);
608 rp->x = rr->left;
609 rp->y = REVERT(rr->top);
610 rp->width = rr->right - rr->left + 1;
611 rp->height = rr->top - rr->bottom + 1;
612 }
613
614 while ( prima_make_brush( XX, mix++))
615 XFillRectangles( DISP, XX-> gdrawable, XX-> gc, r, nr);
616
617 XCHECKPOINT;
618 XFLUSH;
619 free( r);
620 return true;
621 }
622
623 Bool
apc_gp_alpha(Handle self,int alpha,int x1,int y1,int x2,int y2)624 apc_gp_alpha( Handle self, int alpha, int x1, int y1, int x2, int y2)
625 {
626 DEFXX;
627 int pixel;
628
629 if ( PObject( self)-> options. optInDrawInfo) return false;
630 if ( !XF_IN_PAINT(XX)) return false;
631 if ( !XF_LAYERED(XX)) return false;
632 if ( XT_IS_WIDGET(XX) && !XX->flags. layered_requested) return false;
633
634 if ( x1 < 0 && y1 < 0 && x2 < 0 && y2 < 0) {
635 x1 = 0; y1 = 0;
636 x2 = XX-> size. x - 1;
637 y2 = XX-> size. y - 1;
638 }
639 SHIFT( x1, y1); SHIFT( x2, y2);
640 SORT( x1, x2); SORT( y1, y2);
641 RANGE4( x1, y1, x2, y2);
642
643 pixel = ((alpha << guts. argb_bits. alpha_range) >> 8) << guts. argb_bits. alpha_shift;
644 XSetForeground( DISP, XX-> gc, pixel);
645 XX-> flags. brush_fore = 0;
646 XSetPlaneMask( DISP, XX-> gc, guts. argb_bits. alpha_mask);
647 XFillRectangle( DISP, XX-> gdrawable, XX-> gc, x1, REVERT( y2), x2 - x1 + 1, y2 - y1 + 1);
648 XSetPlaneMask( DISP, XX-> gc, AllPlanes);
649 XFLUSH;
650
651 return true;
652 }
653
654 Bool
apc_gp_can_draw_alpha(Handle self)655 apc_gp_can_draw_alpha( Handle self)
656 {
657 DEFXX;
658 if (XT_IS_BITMAP(XX) || (( XT_IS_PIXMAP(XX) || XT_IS_APPLICATION(XX)) && guts.depth==1))
659 return false;
660 else
661 return
662 guts.render_extension
663 #ifdef WITH_COCOA
664 && !prima_cocoa_is_x11_local()
665 #endif
666 ;
667 }
668
669 Bool
apc_gp_clear(Handle self,int x1,int y1,int x2,int y2)670 apc_gp_clear( Handle self, int x1, int y1, int x2, int y2)
671 {
672 DEFXX;
673
674 if ( PObject( self)-> options. optInDrawInfo) return false;
675 if ( !XF_IN_PAINT(XX)) return false;
676
677 if ( x1 < 0 && y1 < 0 && x2 < 0 && y2 < 0) {
678 x1 = 0; y1 = 0;
679 x2 = XX-> size. x - 1;
680 y2 = XX-> size. y - 1;
681 }
682 SHIFT( x1, y1); SHIFT( x2, y2);
683 SORT( x1, x2); SORT( y1, y2);
684 RANGE4( x1, y1, x2, y2);
685
686 /* clean color entries, leave just background & foreground. XXX */
687 if ( guts. dynamicColors && x1 <= 0 && x2 > XX-> size.x && y1 <= 0 && y2 >= XX-> size.y) {
688 prima_palette_free(self,false);
689 apc_gp_set_color(self, XX-> fore. color);
690 apc_gp_set_back_color(self, XX-> back. color);
691 }
692
693 XSetForeground( DISP, XX-> gc, XX-> back. primary);
694 if ( XX-> back. balance > 0) {
695 Pixmap p = prima_get_hatch( &guts. ditherPatterns[ XX-> back. balance]);
696 if ( p) {
697 XSetFillStyle( DISP, XX-> gc, FillOpaqueStippled);
698 XSetStipple( DISP, XX-> gc, p);
699 XSetBackground( DISP, XX-> gc, XX-> back. secondary);
700 } else
701 XSetFillStyle( DISP, XX-> gc, FillSolid);
702 } else
703 XSetFillStyle( DISP, XX-> gc, FillSolid);
704 XX-> flags. brush_fore = 0;
705 XFillRectangle( DISP, XX-> gdrawable, XX-> gc, x1, REVERT( y2), x2 - x1 + 1, y2 - y1 + 1);
706 XFLUSH;
707
708 return true;
709 }
710
711 #define GRAD 57.29577951
712
713 Bool
apc_gp_chord(Handle self,int x,int y,int dX,int dY,double angleStart,double angleEnd)714 apc_gp_chord( Handle self, int x, int y, int dX, int dY, double angleStart, double angleEnd)
715 {
716 int compl, needf;
717 DEFXX;
718
719 if ( PObject( self)-> options. optInDrawInfo) return false;
720 if ( !XF_IN_PAINT(XX)) return false;
721 if ( dX <= 0 || dY <= 0) return false;
722 RANGE4(x, y, dX, dY);
723
724 SHIFT( x, y);
725 y = REVERT( y);
726 PURE_FOREGROUND;
727 compl = arc_completion( &angleStart, &angleEnd, &needf);
728 calculate_ellipse_divergence();
729 while ( compl--)
730 XDrawArc( DISP, XX-> gdrawable, XX-> gc, ELLIPSE_RECT, 0, 360 * 64);
731 if ( !needf) return true;
732 XDrawArc( DISP, XX-> gdrawable, XX-> gc, ELLIPSE_RECT,
733 angleStart * 64, ( angleEnd - angleStart) * 64);
734 XDrawLine( DISP, XX-> gdrawable, XX-> gc,
735 x + cos( angleStart / GRAD) * dX / 2, y - sin( angleStart / GRAD) * dY / 2,
736 x + cos( angleEnd / GRAD) * dX / 2, y - sin( angleEnd / GRAD) * dY / 2);
737 XFLUSH;
738 return true;
739 }
740
741 Bool
apc_gp_draw_poly(Handle self,int n,Point * pp)742 apc_gp_draw_poly( Handle self, int n, Point *pp)
743 {
744 DEFXX;
745 int i;
746 int x = XX-> gtransform. x + XX-> btransform. x;
747 int y = XX-> size. y - 1 - XX-> gtransform. y - XX-> btransform. y;
748 XPoint *p;
749
750 if ( PObject( self)-> options. optInDrawInfo) return false;
751 if ( !XF_IN_PAINT(XX)) return false;
752
753 if ((p = malloc( sizeof( XPoint)*n)) == NULL)
754 return false;
755
756 for ( i = 0; i < n; i++) {
757 p[i].x = pp[i].x + x;
758 p[i].y = y - pp[i].y;
759 RANGE2(p[i].x, p[i].y);
760 }
761
762 PURE_FOREGROUND;
763 XDrawLines( DISP, XX-> gdrawable, XX-> gc, p, n, CoordModeOrigin);
764
765 free( p);
766 XFLUSH;
767 return true;
768 }
769
770 Bool
apc_gp_draw_poly2(Handle self,int np,Point * pp)771 apc_gp_draw_poly2( Handle self, int np, Point *pp)
772 {
773 DEFXX;
774 int i;
775 int x = XX-> gtransform. x + XX-> btransform. x;
776 int y = XX-> size. y - 1 - XX-> gtransform. y - XX-> btransform. y;
777 XSegment *s;
778 int n = np / 2;
779
780 if ( PObject( self)-> options. optInDrawInfo) return false;
781 if ( !XF_IN_PAINT(XX)) return false;
782
783 if ((s = malloc( sizeof( XSegment)*n)) == NULL) return false;
784
785 for ( i = 0; i < n; i++) {
786 s[i].x1 = pp[i*2].x + x;
787 s[i].y1 = y - pp[i*2].y;
788 s[i].x2 = pp[i*2+1].x + x;
789 s[i].y2 = y - pp[i*2+1].y;
790 RANGE4(s[i].x1, s[i].y1, s[i].x2, s[i].y2);
791 }
792
793 PURE_FOREGROUND;
794 XDrawSegments( DISP, XX-> gdrawable, XX-> gc, s, n);
795
796 free( s);
797 XFLUSH;
798 return true;
799 }
800
801 Bool
apc_gp_ellipse(Handle self,int x,int y,int dX,int dY)802 apc_gp_ellipse( Handle self, int x, int y, int dX, int dY)
803 {
804 DEFXX;
805
806 if ( dX == 1 || dY == 1 ) /* Xorg bug */
807 return apc_gp_rectangle( self, x - dX / 2, y - dY / 2, x + dX / 2, y + dY / 2);
808
809 if ( PObject( self)-> options. optInDrawInfo) return false;
810 if ( !XF_IN_PAINT(XX)) return false;
811 if ( dX <= 0 || dY <= 0) return false;
812 RANGE4(x, y, dX, dY);
813
814 SHIFT( x, y);
815 y = REVERT( y);
816 PURE_FOREGROUND;
817 calculate_ellipse_divergence();
818 XDrawArc( DISP, XX-> gdrawable, XX-> gc, ELLIPSE_RECT, 0, 64*360);
819 XFLUSH;
820 return true;
821 }
822
823 Bool
apc_gp_fill_chord(Handle self,int x,int y,int dX,int dY,double angleStart,double angleEnd)824 apc_gp_fill_chord( Handle self, int x, int y, int dX, int dY, double angleStart, double angleEnd)
825 {
826 DEFXX;
827 int compl, needf, mix = 0;
828
829 if ( PObject( self)-> options. optInDrawInfo) return false;
830 if ( !XF_IN_PAINT(XX)) return false;
831 if ( dX <= 0 || dY <= 0) return false;
832 RANGE4(x, y, dX, dY);
833
834 SHIFT( x, y);
835 y = REVERT( y);
836
837 XSetArcMode( DISP, XX-> gc, ArcChord);
838 FILL_ANTIDEFECT_OPEN;
839
840 while ( prima_make_brush( XX, mix++)) {
841 compl = arc_completion( &angleStart, &angleEnd, &needf);
842 while ( compl--) {
843 XFillArc( DISP, XX-> gdrawable, XX-> gc, x - ( dX + 1) / 2 + 1, y - dY / 2, dX, dY, 0, 64*360);
844 if ( FILL_ANTIDEFECT_REPAIRABLE)
845 XDrawArc( DISP, XX-> gdrawable, XX-> gc, x - ( dX + 1) / 2 + 1, y - dY / 2, dX-1, dY-1, 0, 64*360);
846 }
847
848 if ( needf) {
849 XFillArc( DISP, XX-> gdrawable, XX-> gc, x - ( dX + 1) / 2 + 1, y - dY / 2, dX, dY,
850 angleStart * 64, ( angleEnd - angleStart) * 64);
851 if ( FILL_ANTIDEFECT_REPAIRABLE)
852 XDrawArc( DISP, XX-> gdrawable, XX-> gc, x - ( dX + 1) / 2 + 1, y - dY / 2, dX-1, dY-1,
853 angleStart * 64, ( angleEnd - angleStart) * 64);
854 }
855 }
856 FILL_ANTIDEFECT_CLOSE;
857 XFLUSH;
858 return true;
859 }
860
861 Bool
apc_gp_fill_ellipse(Handle self,int x,int y,int dX,int dY)862 apc_gp_fill_ellipse( Handle self, int x, int y, int dX, int dY)
863 {
864 DEFXX;
865 int mix = 0;
866
867 if ( dX == 1 || dY == 1 ) /* Xorg bug */
868 return apc_gp_bar( self, x - dX / 2, y - dY / 2, x + dX / 2, y + dY / 2);
869
870 if ( PObject( self)-> options. optInDrawInfo) return false;
871 if ( !XF_IN_PAINT(XX)) return false;
872 if ( dX <= 0 || dY <= 0) return false;
873 RANGE4(x, y, dX, dY);
874 SHIFT( x, y);
875 y = REVERT( y);
876
877 FILL_ANTIDEFECT_OPEN;
878 while ( prima_make_brush( XX, mix++)) {
879 XFillArc( DISP, XX-> gdrawable, XX-> gc, x - ( dX + 1) / 2 + 1, y - dY / 2, dX, dY, 0, 64*360);
880 if ( FILL_ANTIDEFECT_REPAIRABLE)
881 XDrawArc( DISP, XX-> gdrawable, XX-> gc, x - ( dX + 1) / 2 + 1, y - dY / 2, dX-1, dY-1, 0, 64*360);
882 }
883 FILL_ANTIDEFECT_CLOSE;
884 XFLUSH;
885 return true;
886 }
887
888 Bool
apc_gp_fill_poly(Handle self,int numPts,Point * points)889 apc_gp_fill_poly( Handle self, int numPts, Point *points)
890 {
891 /* XXX - beware, current implementation will not deal correctly with different rops and tiles */
892 XPoint *p;
893 DEFXX;
894 int i, mix = 0;
895
896 if ( PObject( self)-> options. optInDrawInfo) return false;
897 if ( !XF_IN_PAINT(XX)) return false;
898
899 if ( !( p = malloc(( numPts + 1) * sizeof( XPoint)))) return false;
900
901 for ( i = 0; i < numPts; i++) {
902 p[i]. x = (short)points[i]. x + XX-> gtransform. x + XX-> btransform. x;
903 p[i]. y = (short)REVERT(points[i]. y + XX-> gtransform. y + XX-> btransform. y);
904 RANGE2(p[i].x, p[i].y);
905 }
906 p[numPts]. x = (short)points[0]. x + XX-> gtransform. x + XX-> btransform. x;
907 p[numPts]. y = (short)REVERT(points[0]. y + XX-> gtransform. y + XX-> btransform. y);
908 RANGE2(p[numPts].x, p[numPts].y);
909
910 FILL_ANTIDEFECT_OPEN;
911 if ( guts. limits. XFillPolygon >= numPts) {
912 while ( prima_make_brush( XX, mix++)) {
913 XFillPolygon( DISP, XX-> gdrawable, XX-> gc, p, numPts, ComplexShape, CoordModeOrigin);
914 if ( FILL_ANTIDEFECT_REPAIRABLE) {
915 XDrawLines( DISP, XX-> gdrawable, XX-> gc, p, numPts+1, CoordModeOrigin);
916 }
917 }
918 XCHECKPOINT;
919 } else
920 warn( "Prima::Drawable::fill_poly: too many points");
921 FILL_ANTIDEFECT_CLOSE;
922 free( p);
923 XFLUSH;
924 return true;
925 }
926
927 Bool
apc_gp_fill_sector(Handle self,int x,int y,int dX,int dY,double angleStart,double angleEnd)928 apc_gp_fill_sector( Handle self, int x, int y, int dX, int dY, double angleStart, double angleEnd)
929 {
930 DEFXX;
931 int compl, needf, mix = 0;
932
933 if ( PObject( self)-> options. optInDrawInfo) return false;
934 if ( !XF_IN_PAINT(XX)) return false;
935 if ( dX <= 0 || dY <= 0) return false;
936 RANGE4(x, y, dX, dY);
937
938 SHIFT( x, y);
939 y = REVERT( y);
940 XSetArcMode( DISP, XX-> gc, ArcPieSlice);
941
942 FILL_ANTIDEFECT_OPEN;
943 while ( prima_make_brush( XX, mix++)) {
944 compl = arc_completion( &angleStart, &angleEnd, &needf);
945 while ( compl--) {
946 XFillArc( DISP, XX-> gdrawable, XX-> gc, x - ( dX + 1) / 2 + 1, y - dY / 2, dX, dY, 0, 64*360);
947 if ( FILL_ANTIDEFECT_REPAIRABLE)
948 XDrawArc( DISP, XX-> gdrawable, XX-> gc, x - ( dX + 1) / 2 + 1, y - dY / 2, dX-1, dY-1, 0, 64*360);
949 }
950
951 if ( needf) {
952 XFillArc( DISP, XX-> gdrawable, XX-> gc, x - ( dX + 1) / 2 + 1, y - dY / 2, dX, dY,
953 angleStart * 64, ( angleEnd - angleStart) * 64);
954 if ( FILL_ANTIDEFECT_REPAIRABLE)
955 XDrawArc( DISP, XX-> gdrawable, XX-> gc, x - ( dX + 1) / 2 + 1, y - dY / 2, dX-1, dY-1,
956 angleStart * 64, ( angleEnd - angleStart) * 64);
957 }
958 }
959 FILL_ANTIDEFECT_CLOSE;
960 XFLUSH;
961 return true;
962 }
963
964 static int
get_pixel_depth(int depth)965 get_pixel_depth( int depth)
966 {
967 if ( depth == 1) return 1; else
968 if ( depth <= 4) return 4; else
969 if ( depth <= 8) return 8; else
970 if ( depth <= 16) return 16; else
971 if ( depth <= 24) return 24; else
972 return 32;
973 }
974
975
976 static uint32_t
color_to_pixel(Handle self,Color color,int depth)977 color_to_pixel( Handle self, Color color, int depth)
978 {
979 uint32_t pv;
980
981 if ( depth == 1) {
982 pv = color ? 1 : 0;
983 } else if ( guts.palSize > 0 ) {
984 pv = prima_color_find( self, color, -1, NULL, RANK_FREE);
985 } else {
986 PRGBABitDescription bd = GET_RGBA_DESCRIPTION;
987 switch ( depth) {
988 case 16:
989 case 24:
990 case 32:
991 pv =
992 (((COLOR_R(color) << bd-> red_range ) >> 8) << bd-> red_shift) |
993 (((COLOR_G(color) << bd-> green_range) >> 8) << bd-> green_shift) |
994 (((COLOR_B(color) << bd-> blue_range ) >> 8) << bd-> blue_shift);
995 if ( guts.machine_byte_order != guts.byte_order)
996 switch( depth) {
997 case 16:
998 pv = REVERSE_BYTES_16( pv);
999 break;
1000 case 24:
1001 pv = REVERSE_BYTES_24( pv);
1002 break;
1003 case 32:
1004 pv = REVERSE_BYTES_32( pv);
1005 break;
1006 }
1007 break;
1008 default:
1009 warn("UAG_005: Not supported pixel depth");
1010 return 0;
1011 }
1012 }
1013 return pv;
1014 }
1015
1016 typedef struct {
1017 XImage * i;
1018 Rect clip;
1019 uint32_t color;
1020 int depth;
1021 int y;
1022 Bool singleBorder;
1023 XDrawable drawable;
1024 GC gc;
1025 int first;
1026 PList * lists;
1027 } FillSession;
1028
1029 static Bool
fs_get_pixel(FillSession * fs,int x,int y)1030 fs_get_pixel( FillSession * fs, int x, int y)
1031 {
1032 if ( x < fs-> clip. left || x > fs-> clip. right || y < fs-> clip. top || y > fs-> clip. bottom) {
1033 return false;
1034 }
1035
1036 if ( fs-> lists[ y - fs-> first]) {
1037 PList l = fs-> lists[ y - fs-> first];
1038 int i;
1039 for ( i = 0; i < l-> count; i+=2) {
1040 if (((int) l-> items[i+1] >= x) && ((int)l->items[i] <= x))
1041 return false;
1042 }
1043 }
1044
1045 if ( !fs-> i || y != fs-> y) {
1046 XCHECKPOINT;
1047 if ( fs-> i) XDestroyImage( fs-> i);
1048 XCHECKPOINT;
1049 fs-> i = XGetImage( DISP, fs-> drawable, fs-> clip. left, y,
1050 fs-> clip. right - fs-> clip. left + 1, 1,
1051 ( fs-> depth == 1) ? 1 : AllPlanes,
1052 ( fs-> depth == 1) ? XYPixmap : ZPixmap);
1053 XCHECKPOINT;
1054 if ( !fs-> i) {
1055 return false;
1056 }
1057 fs-> y = y;
1058 }
1059
1060 x -= fs-> clip. left;
1061
1062 switch( fs-> depth) {
1063 case 1:
1064 {
1065 Byte xz = *((Byte*)(fs->i->data) + (x >> 3));
1066 uint32_t v = ( guts.bit_order == MSBFirst) ?
1067 ( xz & ( 0x80 >> ( x & 7)) ? 1 : 0) :
1068 ( xz & ( 0x01 << ( x & 7)) ? 1 : 0);
1069 return fs-> singleBorder ?
1070 ( v == fs-> color) : ( v != fs-> color);
1071 }
1072 break;
1073 case 4:
1074 {
1075 Byte xz = *((Byte*)(fs->i->data) + (x >> 1));
1076 uint32_t v = ( x & 1) ? ( xz & 0xF) : ( xz >> 4);
1077 return fs-> singleBorder ?
1078 ( v == fs-> color) : ( v != fs-> color);
1079 }
1080 break;
1081 case 8:
1082 return fs-> singleBorder ?
1083 ( fs-> color == *((Byte*)(fs->i->data) + x)) :
1084 ( fs-> color != *((Byte*)(fs->i->data) + x));
1085 case 16:
1086 return fs-> singleBorder ?
1087 ( fs-> color == *((uint16_t*)(fs->i->data) + x)):
1088 ( fs-> color != *((uint16_t*)(fs->i->data) + x));
1089 case 24:
1090 return fs-> singleBorder ?
1091 ( memcmp(( Byte*)(fs->i->data) + x, &fs->color, 3) == 0) :
1092 ( memcmp(( Byte*)(fs->i->data) + x, &fs->color, 3) != 0);
1093 case 32:
1094 return fs-> singleBorder ?
1095 ( fs-> color == *((uint32_t*)(fs->i->data) + x)):
1096 ( fs-> color != *((uint32_t*)(fs->i->data) + x));
1097 }
1098 return false;
1099 }
1100
1101 static void
hline(FillSession * fs,int x1,int y,int x2)1102 hline( FillSession * fs, int x1, int y, int x2)
1103 {
1104 XFillRectangle( DISP, fs-> drawable, fs-> gc, x1, y, x2 - x1 + 1, 1);
1105
1106 if ( y == fs-> y && fs-> i) {
1107 XDestroyImage( fs-> i);
1108 fs-> i = NULL;
1109 }
1110
1111 y -= fs-> first;
1112
1113 if ( fs-> lists[y] == NULL)
1114 fs-> lists[y] = plist_create( 32, 128);
1115 list_add( fs-> lists[y], ( Handle) x1);
1116 list_add( fs-> lists[y], ( Handle) x2);
1117 }
1118
1119 static int
fill(FillSession * fs,int sx,int sy,int d,int pxl,int pxr)1120 fill( FillSession * fs, int sx, int sy, int d, int pxl, int pxr)
1121 {
1122 int x, xr = sx;
1123 while ( sx > fs-> clip. left && fs_get_pixel( fs, sx - 1, sy)) sx--;
1124 while ( xr < fs-> clip. right && fs_get_pixel( fs, xr + 1, sy)) xr++;
1125 hline( fs, sx, sy, xr);
1126
1127 if ( sy + d >= fs-> clip. top && sy + d <= fs-> clip. bottom) {
1128 x = sx;
1129 while ( x <= xr) {
1130 if ( fs_get_pixel( fs, x, sy + d)) {
1131 x = fill( fs, x, sy + d, d, sx, xr);
1132 }
1133 x++;
1134 }
1135 }
1136
1137 if ( sy - d >= fs-> clip. top && sy - d <= fs-> clip. bottom) {
1138 x = sx;
1139 while ( x < pxl) {
1140 if ( fs_get_pixel( fs, x, sy - d)) {
1141 x = fill( fs, x, sy - d, -d, sx, xr);
1142 }
1143 x++;
1144 }
1145 x = pxr;
1146 while ( x <= xr) {
1147 if ( fs_get_pixel( fs, x, sy - d)) {
1148 x = fill( fs, x, sy - d, -d, sx, xr);
1149 }
1150 x++;
1151 }
1152 }
1153 return xr;
1154 }
1155
1156 Bool
apc_gp_flood_fill(Handle self,int x,int y,Color color,Bool singleBorder)1157 apc_gp_flood_fill( Handle self, int x, int y, Color color, Bool singleBorder)
1158 {
1159 DEFXX;
1160 Bool ret = false;
1161 XRectangle cr;
1162 FillSession s;
1163 int mix = 0, hint;
1164
1165 if ( !opt_InPaint) return false;
1166
1167 s. singleBorder = singleBorder;
1168 s. drawable = XX-> gdrawable;
1169 s. gc = XX-> gc;
1170 SHIFT( x, y);
1171 y = REVERT( y);
1172 color = prima_map_color( color, &hint);
1173 prima_gp_get_clip_rect( self, &cr, 1);
1174
1175 s. clip. left = cr. x;
1176 s. clip. top = cr. y;
1177 s. clip. right = cr. x + cr. width - 1;
1178 s. clip. bottom = cr. y + cr. height - 1;
1179 if ( cr. width <= 0 || cr. height <= 0) return false;
1180 s. i = NULL;
1181 s. depth = XT_IS_BITMAP(X(self)) ? 1 : guts. idepth;
1182 s. depth = get_pixel_depth( s. depth);
1183 s. color = hint ?
1184 (( hint == COLORHINT_BLACK) ? LOGCOLOR_BLACK : LOGCOLOR_WHITE)
1185 : color_to_pixel( self, color, s.depth);
1186
1187 s. first = s. clip. top;
1188 if ( !( s. lists = malloc(( s. clip. bottom - s. clip. top + 1) * sizeof( void*))))
1189 return false;
1190 bzero( s. lists, ( s. clip. bottom - s. clip. top + 1) * sizeof( void*));
1191
1192 prima_make_brush( XX, mix++);
1193 if ( fs_get_pixel( &s, x, y)) {
1194 fill( &s, x, y, -1, x, x);
1195 ret = true;
1196 }
1197
1198 while ( prima_make_brush( XX, mix++)) {
1199 for ( y = 0; y < s. clip. bottom - s. clip. top + 1; y++)
1200 if ( s. lists[y])
1201 for ( x = 0; x < s.lists[y]-> count; x += 2)
1202 XFillRectangle( DISP, s.drawable, s.gc,
1203 (int)s.lists[y]->items[x], y,
1204 (int)s.lists[y]->items[x+1] - (int)s.lists[y]->items[x], 1);
1205 }
1206
1207 if ( s. i) XDestroyImage( s. i);
1208
1209 for ( x = 0; x < s. clip. bottom - s. clip. top + 1; x++)
1210 if ( s. lists[x])
1211 plist_destroy( s.lists[x]);
1212 free( s. lists);
1213 XFLUSH;
1214
1215 return ret;
1216 }
1217
1218 Color
apc_gp_get_pixel(Handle self,int x,int y)1219 apc_gp_get_pixel( Handle self, int x, int y)
1220 {
1221 DEFXX;
1222 Color c = 0;
1223 XImage *im;
1224 Bool pixmap;
1225 uint32_t p32 = 0;
1226
1227 if ( !opt_InPaint) return clInvalid;
1228 SHIFT( x, y);
1229
1230 if ( x < 0 || x >= XX-> size.x || y < 0 || y >= XX-> size.y)
1231 return clInvalid;
1232
1233 if ( XT_IS_DBM(XX)) {
1234 pixmap = XT_IS_PIXMAP(XX) ? true : false;
1235 } else if ( XT_IS_BITMAP(XX)) {
1236 pixmap = 0;
1237 } else {
1238 pixmap = guts. idepth > 1;
1239 }
1240
1241 im = XGetImage( DISP, XX-> gdrawable, x, XX-> size.y - y - 1, 1, 1,
1242 pixmap ? AllPlanes : 1,
1243 pixmap ? ZPixmap : XYPixmap);
1244 XCHECKPOINT;
1245 if ( !im) return clInvalid;
1246
1247 if ( pixmap) {
1248 if ( guts. palSize > 0) {
1249 int pixel;
1250 if ( guts. idepth <= 8)
1251 pixel = (*( U8*)( im-> data)) & (( 1 << guts.idepth) - 1);
1252 else
1253 pixel = (*( U16*)( im-> data)) & (( 1 << guts.idepth) - 1);
1254 if ( guts.palette[pixel]. rank == RANK_FREE) {
1255 XColor xc;
1256 xc.pixel = pixel;
1257 XQueryColors( DISP, guts. defaultColormap, &xc, 1);
1258 c = RGB_COMPOSITE(xc.red>>8,xc.green>>8,xc.blue>>8);
1259 } else
1260 c = guts.palette[pixel]. composite;
1261 } else {
1262 PRGBABitDescription bd = GET_RGBA_DESCRIPTION;
1263 int r, g, b, rmax, gmax, bmax, depth;
1264 rmax = gmax = bmax = 0xff;
1265 depth = XF_LAYERED(XX) ? guts. argb_visual. depth : guts. idepth;
1266 switch ( depth) {
1267 case 16:
1268 p32 = *(( uint16_t*)(im-> data));
1269 if ( guts.machine_byte_order != guts.byte_order)
1270 p32 = REVERSE_BYTES_16(p32);
1271 rmax = 0xff & ( 0xff << ( 8 - bd-> red_range));
1272 gmax = 0xff & ( 0xff << ( 8 - bd-> green_range));
1273 bmax = 0xff & ( 0xff << ( 8 - bd-> blue_range));
1274 goto COMP;
1275 case 24:
1276 p32 = (im-> data[0] << 16) | (im-> data[1] << 8) | im-> data[2];
1277 if ( guts.machine_byte_order != guts.byte_order)
1278 p32 = REVERSE_BYTES_24(p32);
1279 goto COMP;
1280 case 32:
1281 p32 = *(( uint32_t*)(im-> data));
1282 if ( guts.machine_byte_order != guts.byte_order)
1283 p32 = REVERSE_BYTES_32(p32);
1284 COMP:
1285 r = ((((p32 & bd-> red_mask) >> bd->red_shift) << 8) >> bd-> red_range) & 0xff;
1286 g = ((((p32 & bd-> green_mask) >> bd->green_shift) << 8) >> bd-> green_range) & 0xff;
1287 b = ((((p32 & bd-> blue_mask) >> bd->blue_shift) << 8) >> bd-> blue_range) & 0xff;
1288 if ( r == rmax ) r = 0xff;
1289 if ( g == gmax ) g = 0xff;
1290 if ( b == bmax ) b = 0xff;
1291 c = b | ( g << 8 ) | ( r << 16);
1292 break;
1293 default:
1294 warn("UAG_009: get_pixel not implemented for %d depth", guts.idepth);
1295 }
1296 }
1297 } else {
1298 c = ( im-> data[0] & ((guts.bit_order == MSBFirst) ? 0x80 : 1))
1299 ? 0xffffff : 0;
1300 }
1301
1302 XDestroyImage( im);
1303 return c;
1304 }
1305
1306 Color
apc_gp_get_nearest_color(Handle self,Color color)1307 apc_gp_get_nearest_color( Handle self, Color color)
1308 {
1309 if ( guts. palSize > 0)
1310 return guts. palette[ prima_color_find( self, color, -1, NULL, RANK_FREE)]. composite;
1311 if ( guts. visualClass == TrueColor || guts. visualClass == DirectColor) {
1312 XColor xc;
1313 xc. red = COLOR_R16(color);
1314 xc. green = COLOR_G16(color);
1315 xc. blue = COLOR_B16(color);
1316 if ( XAllocColor( DISP, guts. defaultColormap, &xc)) {
1317 XFreeColors( DISP, guts. defaultColormap, &xc. pixel, 1, 0);
1318 return
1319 (( xc. red & 0xFF00) << 8) |
1320 (( xc. green & 0xFF00)) |
1321 (( xc. blue & 0xFF00) >> 8);
1322 }
1323 }
1324 return color;
1325 }
1326
1327 PRGBColor
apc_gp_get_physical_palette(Handle self,int * colors)1328 apc_gp_get_physical_palette( Handle self, int * colors)
1329 {
1330 int i;
1331 PRGBColor p;
1332 XColor * xc;
1333
1334 *colors = 0;
1335
1336 if ( guts. palSize == 0) return NULL;
1337 if ( !( p = malloc( guts. palSize * sizeof( RGBColor))))
1338 return NULL;
1339 if ( !( xc = malloc( guts. palSize * sizeof( XColor)))) {
1340 free( p);
1341 return NULL;
1342 }
1343 for ( i = 0; i < guts. palSize; i++) xc[i]. pixel = i;
1344 XQueryColors( DISP, guts. defaultColormap, xc, guts. palSize);
1345 XCHECKPOINT;
1346 for ( i = 0; i < guts. palSize; i++) {
1347 p[i]. r = xc[i]. red >> 8;
1348 p[i]. g = xc[i]. green >> 8;
1349 p[i]. b = xc[i]. blue >> 8;
1350 }
1351 free( xc);
1352 *colors = guts. palSize;
1353 return p;
1354 }
1355
1356 Bool
apc_gp_line(Handle self,int x1,int y1,int x2,int y2)1357 apc_gp_line( Handle self, int x1, int y1, int x2, int y2)
1358 {
1359 DEFXX;
1360
1361 if ( PObject( self)-> options. optInDrawInfo) return false;
1362 if ( !XF_IN_PAINT(XX)) return false;
1363
1364 SHIFT( x1, y1); SHIFT( x2, y2);
1365 RANGE4(x1, y1, x2, y2); /* not really correct */
1366 PURE_FOREGROUND;
1367 if (((int)(XX-> paint_line_width + .5) == 0) && (x1 == x2 || y1 == y2)) {
1368 XGCValues gcv;
1369 gcv. line_width = 1;
1370 XChangeGC( DISP, XX-> gc, GCLineWidth, &gcv);
1371 }
1372 XDrawLine( DISP, XX-> gdrawable, XX-> gc, x1, REVERT( y1), x2, REVERT( y2));
1373 if (((int)(XX-> paint_line_width + .5) == 0) && (x1 == x2 || y1 == y2)) {
1374 XGCValues gcv;
1375 gcv. line_width = 0;
1376 XChangeGC( DISP, XX-> gc, GCLineWidth, &gcv);
1377 }
1378 XFLUSH;
1379 return true;
1380 }
1381
1382 Bool
apc_gp_rectangle(Handle self,int x1,int y1,int x2,int y2)1383 apc_gp_rectangle( Handle self, int x1, int y1, int x2, int y2)
1384 {
1385 DEFXX;
1386 int lw = XX-> paint_line_width + .5;
1387
1388 if ( PObject( self)-> options. optInDrawInfo) return false;
1389 if ( !XF_IN_PAINT(XX)) return false;
1390
1391 SHIFT( x1, y1); SHIFT( x2, y2);
1392 SORT( x1, x2); SORT( y1, y2);
1393 RANGE4(x1, y1, x2, y2);
1394 PURE_FOREGROUND;
1395 if ( lw > 0 && (lw % 2) == 0) {
1396 y2--;
1397 y1--;
1398 }
1399 XDrawRectangle( DISP, XX-> gdrawable, XX-> gc, x1, REVERT( y2), x2 - x1, y2 - y1);
1400 XCHECKPOINT;
1401 XFLUSH;
1402 return true;
1403 }
1404
1405 Bool
apc_gp_sector(Handle self,int x,int y,int dX,int dY,double angleStart,double angleEnd)1406 apc_gp_sector( Handle self, int x, int y, int dX, int dY, double angleStart, double angleEnd)
1407 {
1408 int compl, needf;
1409 DEFXX;
1410
1411 if ( PObject( self)-> options. optInDrawInfo) return false;
1412 if ( !XF_IN_PAINT(XX)) return false;
1413 if ( dX <= 0 || dY <= 0) return false;
1414 RANGE4(x, y, dX, dY);
1415
1416 SHIFT( x, y);
1417 y = REVERT( y);
1418
1419 compl = arc_completion( &angleStart, &angleEnd, &needf);
1420 PURE_FOREGROUND;
1421 calculate_ellipse_divergence();
1422 while ( compl--)
1423 XDrawArc( DISP, XX-> gdrawable, XX-> gc, ELLIPSE_RECT,
1424 0, 360 * 64);
1425 if ( !needf) return true;
1426 XDrawArc( DISP, XX-> gdrawable, XX-> gc, ELLIPSE_RECT,
1427 angleStart * 64, ( angleEnd - angleStart) * 64);
1428 XDrawLine( DISP, XX-> gdrawable, XX-> gc,
1429 x + cos( angleStart / GRAD) * dX / 2, y - sin( angleStart / GRAD) * dY / 2,
1430 x, y
1431 );
1432 XDrawLine( DISP, XX-> gdrawable, XX-> gc,
1433 x, y,
1434 x + cos( angleEnd / GRAD) * dX / 2, y - sin( angleEnd / GRAD) * dY / 2
1435 );
1436 XFLUSH;
1437 return true;
1438 }
1439
1440 Bool
apc_gp_set_palette(Handle self)1441 apc_gp_set_palette( Handle self)
1442 {
1443 if ( XT_IS_WIDGET(X(self))) return true;
1444 return prima_palette_replace( self, false);
1445 }
1446
1447 Bool
apc_gp_set_pixel(Handle self,int x,int y,Color color)1448 apc_gp_set_pixel( Handle self, int x, int y, Color color)
1449 {
1450 DEFXX;
1451
1452 if ( PObject( self)-> options. optInDrawInfo) return false;
1453 if ( !XF_IN_PAINT(XX)) return false;
1454
1455 SHIFT( x, y);
1456 XSetForeground( DISP, XX-> gc, prima_allocate_color( self, color, NULL));
1457 XDrawPoint( DISP, XX-> gdrawable, XX-> gc, x, REVERT( y));
1458 XX-> flags. brush_fore = 0;
1459 XFLUSH;
1460 return true;
1461 }
1462
1463 /* gpi settings */
1464 int
apc_gp_get_alpha(Handle self)1465 apc_gp_get_alpha( Handle self)
1466 {
1467 DEFXX;
1468 if ( XF_IN_PAINT(XX)) {
1469 return XX-> paint_alpha;
1470 } else {
1471 return XX-> alpha;
1472 }
1473 }
1474
1475 Bool
apc_gp_get_antialias(Handle self)1476 apc_gp_get_antialias( Handle self)
1477 {
1478 DEFXX;
1479 return XF_IN_PAINT(XX) ? XX-> flags.antialias : XX->flags.saved_antialias;
1480 }
1481
1482 Color
apc_gp_get_back_color(Handle self)1483 apc_gp_get_back_color( Handle self)
1484 {
1485 DEFXX;
1486 return ( XF_IN_PAINT(XX)) ? XX-> back. color : prima_map_color( XX-> saved_back, NULL);
1487 }
1488
1489 int
apc_gp_get_bpp(Handle self)1490 apc_gp_get_bpp( Handle self)
1491 {
1492 DEFXX;
1493 if ( XT_IS_BITMAP(XX)) return 1;
1494 if ( XF_LAYERED(XX)) return guts. argb_depth;
1495 return guts. depth;
1496 }
1497
1498 Color
apc_gp_get_color(Handle self)1499 apc_gp_get_color( Handle self)
1500 {
1501 DEFXX;
1502 return ( XF_IN_PAINT(XX)) ? XX-> fore. color : prima_map_color(XX-> saved_fore, NULL);
1503 }
1504
1505 unsigned long *
apc_gp_get_font_ranges(Handle self,int * count)1506 apc_gp_get_font_ranges( Handle self, int * count)
1507 {
1508 DEFXX;
1509 unsigned long * ret = NULL;
1510 XFontStruct * fs;
1511 #ifdef USE_XFT
1512 if ( XX-> font-> xft)
1513 return prima_xft_get_font_ranges( self, count);
1514 #endif
1515 fs = XX-> font-> fs;
1516 *count = (fs-> max_byte1 - fs-> min_byte1 + 1) * 2;
1517 if (( ret = malloc( sizeof( unsigned long) * ( *count)))) {
1518 int i;
1519 for ( i = fs-> min_byte1; i <= fs-> max_byte1; i++) {
1520 ret[(i - fs-> min_byte1) * 2 + 0] = i * 256 + fs-> min_char_or_byte2;
1521 ret[(i - fs-> min_byte1) * 2 + 1] = i * 256 + fs-> max_char_or_byte2;
1522 }
1523 }
1524 return ret;
1525 }
1526
1527 char *
apc_gp_get_font_languages(Handle self)1528 apc_gp_get_font_languages( Handle self)
1529 {
1530 DEFXX;
1531 char * ret;
1532 #ifdef USE_XFT
1533 if ( XX-> font-> xft)
1534 return prima_xft_get_font_languages(self);
1535 #endif
1536 if ( XX-> font-> flags.funky )
1537 return NULL;
1538 if ( !( ret = malloc(4)))
1539 return NULL;
1540 memcpy(ret, "en\0\0", 4);
1541 return ret;
1542 }
1543
1544 int
apc_gp_get_fill_mode(Handle self)1545 apc_gp_get_fill_mode( Handle self)
1546 {
1547 DEFXX;
1548 return XF_IN_PAINT(XX) ? XX->fill_mode : XX->saved_fill_mode;
1549 }
1550
1551 FillPattern *
apc_gp_get_fill_pattern(Handle self)1552 apc_gp_get_fill_pattern( Handle self)
1553 {
1554 return &(X(self)-> fill_pattern);
1555 }
1556
1557 Point
apc_gp_get_fill_pattern_offset(Handle self)1558 apc_gp_get_fill_pattern_offset( Handle self)
1559 {
1560 return X(self)-> fill_pattern_offset;
1561 }
1562
1563 int
apc_gp_get_line_end(Handle self)1564 apc_gp_get_line_end( Handle self)
1565 {
1566 DEFXX;
1567 int cap;
1568 XGCValues gcv;
1569
1570 if ( XF_IN_PAINT(XX)) {
1571 if ( XGetGCValues( DISP, XX-> gc, GCCapStyle, &gcv) == 0) {
1572 warn( "UAG_006: error querying GC values");
1573 cap = CapButt;
1574 } else {
1575 cap = gcv. cap_style;
1576 }
1577 } else {
1578 cap = XX-> gcv. cap_style;
1579 }
1580 if ( cap == CapRound)
1581 return leRound;
1582 else if ( cap == CapProjecting)
1583 return leSquare;
1584 return leFlat;
1585 }
1586
1587 int
apc_gp_get_line_join(Handle self)1588 apc_gp_get_line_join( Handle self)
1589 {
1590 DEFXX;
1591 int join;
1592 XGCValues gcv;
1593
1594 if ( XF_IN_PAINT(XX)) {
1595 if ( XGetGCValues( DISP, XX-> gc, GCJoinStyle, &gcv) == 0) {
1596 warn( "UAG_006: error querying GC values");
1597 join = JoinRound;
1598 } else {
1599 join = gcv. join_style;
1600 }
1601 } else {
1602 join = XX-> gcv. join_style;
1603 }
1604 if ( join == JoinMiter)
1605 return ljMiter;
1606 else if ( join == JoinBevel)
1607 return ljBevel;
1608 return ljRound;
1609 }
1610
1611 float
apc_gp_get_line_width(Handle self)1612 apc_gp_get_line_width( Handle self)
1613 {
1614 DEFXX;
1615 return XF_IN_PAINT(XX) ? XX-> paint_line_width : XX-> line_width;
1616 }
1617
1618 int
apc_gp_get_line_pattern(Handle self,unsigned char * dashes)1619 apc_gp_get_line_pattern( Handle self, unsigned char *dashes)
1620 {
1621 DEFXX;
1622 int n;
1623 if ( XF_IN_PAINT(XX)) {
1624 n = XX-> paint_ndashes;
1625 if ( XX-> paint_dashes)
1626 memcpy( dashes, XX-> paint_dashes, n);
1627 else
1628 bzero( dashes, n);
1629 } else {
1630 n = XX-> ndashes;
1631 if ( n < 0) {
1632 n = 0;
1633 strcpy(( char*) dashes, "");
1634 } else if ( n == 0) {
1635 n = 1;
1636 strcpy(( char*) dashes, "\1");
1637 } else {
1638 memcpy( dashes, XX-> dashes, n);
1639 }
1640 }
1641 return n;
1642 }
1643
1644 float
apc_gp_get_miter_limit(Handle self)1645 apc_gp_get_miter_limit( Handle self)
1646 {
1647 DEFXX;
1648 /* xorg.miArcJoin: don't miter arcs with less than 11 degrees between them */
1649 if ( XF_IN_PAINT(XX) ) return 1.0 / sin((11.0 * 3.14159265358 / 180) / 2);
1650 return XX->miter_limit;
1651 }
1652
1653 Point
apc_gp_get_resolution(Handle self)1654 apc_gp_get_resolution( Handle self)
1655 {
1656 return guts. resolution;
1657 }
1658
1659 int
apc_gp_get_rop(Handle self)1660 apc_gp_get_rop( Handle self)
1661 {
1662 DEFXX;
1663 if ( XF_IN_PAINT(XX)) {
1664 return XX-> paint_rop;
1665 } else {
1666 return XX-> rop;
1667 }
1668 }
1669
1670 int
apc_gp_get_rop2(Handle self)1671 apc_gp_get_rop2( Handle self)
1672 {
1673 DEFXX;
1674 if ( XF_IN_PAINT(XX))
1675 return XX-> paint_rop2;
1676 else
1677 return XX-> rop2;
1678 }
1679
1680 Point
apc_gp_get_transform(Handle self)1681 apc_gp_get_transform( Handle self)
1682 {
1683 DEFXX;
1684 if ( XF_IN_PAINT(XX)) {
1685 return XX-> gtransform;
1686 } else {
1687 return XX-> transform;
1688 }
1689 }
1690
1691 Bool
apc_gp_get_text_opaque(Handle self)1692 apc_gp_get_text_opaque( Handle self)
1693 {
1694 DEFXX;
1695 if ( XF_IN_PAINT(XX)) {
1696 return XX-> flags. paint_opaque ? true : false;
1697 } else {
1698 return XX-> flags. opaque ? true : false;
1699 }
1700 }
1701
1702 Bool
apc_gp_get_text_out_baseline(Handle self)1703 apc_gp_get_text_out_baseline( Handle self)
1704 {
1705 DEFXX;
1706 if ( XF_IN_PAINT(XX)) {
1707 return XX-> flags. paint_base_line ? true : false;
1708 } else {
1709 return XX-> flags. base_line ? true : false;
1710 }
1711 }
1712
1713 Bool
apc_gp_set_alpha(Handle self,int alpha)1714 apc_gp_set_alpha( Handle self, int alpha)
1715 {
1716 DEFXX;
1717
1718 if (XT_IS_BITMAP(XX) || (( XT_IS_PIXMAP(XX) || XT_IS_APPLICATION(XX)) && guts.depth==1))
1719 alpha = 255;
1720 if ( !guts.render_extension)
1721 alpha = 255;
1722
1723 if ( XF_IN_PAINT(XX)) {
1724 if ( XX-> paint_alpha == alpha)
1725 return true;
1726 XX-> paint_alpha = alpha;
1727 guts.xrender_pen_dirty = true;
1728 } else {
1729 XX-> alpha = alpha;
1730 }
1731 return true;
1732 }
1733
1734 Bool
apc_gp_set_antialias(Handle self,Bool antialias)1735 apc_gp_set_antialias( Handle self, Bool antialias )
1736 {
1737 DEFXX;
1738 if ( antialias ) {
1739 if (XT_IS_BITMAP(XX) || (( XT_IS_PIXMAP(XX) || XT_IS_APPLICATION(XX)) && guts.depth==1))
1740 return false;
1741 if ( !guts.render_extension)
1742 return false;
1743 }
1744 if ( XF_IN_PAINT(XX) ) {
1745 XX-> flags.antialias = antialias;
1746 } else {
1747 XX-> flags.saved_antialias = antialias;
1748 }
1749 return true;
1750 }
1751
1752 Bool
apc_gp_set_back_color(Handle self,Color color)1753 apc_gp_set_back_color( Handle self, Color color)
1754 {
1755 DEFXX;
1756 if ( XF_IN_PAINT(XX)) {
1757 prima_allocate_color( self, color, &XX-> back);
1758 XX-> flags. brush_back = 0;
1759 if ( !XX-> flags. brush_null_hatch)
1760 guts.xrender_pen_dirty = true;
1761 } else
1762 XX-> saved_back = color;
1763 return true;
1764 }
1765
1766 Bool
apc_gp_set_color(Handle self,Color color)1767 apc_gp_set_color( Handle self, Color color)
1768 {
1769 DEFXX;
1770 if ( XF_IN_PAINT(XX)) {
1771 prima_allocate_color( self, color, &XX-> fore);
1772 XX-> flags. brush_fore = 0;
1773 guts.xrender_pen_dirty = true;
1774 } else
1775 XX-> saved_fore = color;
1776 return true;
1777 }
1778
1779 Bool
apc_gp_set_fill_mode(Handle self,int fillMode)1780 apc_gp_set_fill_mode( Handle self, int fillMode)
1781 {
1782 DEFXX;
1783 int fill_rule;
1784 XGCValues gcv;
1785
1786 fill_rule = ((fillMode & fmWinding) == fmAlternate) ? EvenOddRule : WindingRule;
1787 if ( XF_IN_PAINT(XX)) {
1788 gcv. fill_rule = fill_rule;
1789 XX-> fill_mode = fillMode;
1790 XChangeGC( DISP, XX-> gc, GCFillRule, &gcv);
1791 XCHECKPOINT;
1792 } else {
1793 XX-> gcv. fill_rule = fill_rule;
1794 XX-> saved_fill_mode = fillMode;
1795 }
1796 return true;
1797 }
1798
1799 Bool
apc_gp_set_fill_pattern(Handle self,FillPattern pattern)1800 apc_gp_set_fill_pattern( Handle self, FillPattern pattern)
1801 {
1802 DEFXX;
1803 if ( memcmp( pattern, XX-> fill_pattern, sizeof(FillPattern)) == 0)
1804 return true;
1805 XX-> flags. brush_null_hatch =
1806 ( memcmp( pattern, fillPatterns[fpSolid], sizeof(FillPattern)) == 0);
1807 memcpy( XX-> fill_pattern, pattern, sizeof( FillPattern));
1808 if ( XF_IN_PAINT(XX))
1809 guts.xrender_pen_dirty = true;
1810 return true;
1811 }
1812
1813 Bool
apc_gp_set_fill_pattern_offset(Handle self,Point fpo)1814 apc_gp_set_fill_pattern_offset( Handle self, Point fpo)
1815 {
1816 DEFXX;
1817 XGCValues gcv;
1818
1819 fpo. y = 8 - fpo.y;
1820 XX-> fill_pattern_offset = fpo;
1821
1822 if ( XF_IN_PAINT(XX)) {
1823 gcv. ts_x_origin = fpo. x;
1824 gcv. ts_y_origin = fpo. y;
1825 XChangeGC( DISP, XX-> gc, GCTileStipXOrigin | GCTileStipYOrigin, &gcv);
1826 XCHECKPOINT;
1827 if ( !XX-> flags. brush_null_hatch)
1828 guts.xrender_pen_dirty = true;
1829 } else {
1830 XX-> gcv. ts_x_origin = fpo. x;
1831 XX-> gcv. ts_y_origin = fpo. y;
1832 }
1833 return true;
1834 }
1835
1836 /*- see apc_font.c
1837 void
1838 apc_gp_set_font( Handle self, PFont font)
1839 */
1840
1841 Bool
apc_gp_set_line_end(Handle self,int lineEnd)1842 apc_gp_set_line_end( Handle self, int lineEnd)
1843 {
1844 DEFXX;
1845 int cap = CapButt;
1846 XGCValues gcv;
1847
1848 if ( lineEnd == leFlat)
1849 cap = CapButt;
1850 else if ( lineEnd == leSquare)
1851 cap = CapProjecting;
1852 else if ( lineEnd == leRound)
1853 cap = CapRound;
1854
1855 if ( XF_IN_PAINT(XX)) {
1856 gcv. cap_style = cap;
1857 XChangeGC( DISP, XX-> gc, GCCapStyle, &gcv);
1858 XCHECKPOINT;
1859 } else {
1860 XX-> gcv. cap_style = cap;
1861 }
1862 return true;
1863 }
1864
1865 Bool
apc_gp_set_line_join(Handle self,int lineJoin)1866 apc_gp_set_line_join( Handle self, int lineJoin)
1867 {
1868 DEFXX;
1869 int join = JoinRound;
1870 XGCValues gcv;
1871
1872 if ( lineJoin == ljRound)
1873 join = JoinRound;
1874 else if ( lineJoin == ljBevel)
1875 join = JoinBevel;
1876 else if ( lineJoin == ljMiter)
1877 join = JoinMiter;
1878
1879 if ( XF_IN_PAINT(XX)) {
1880 gcv. join_style = join;
1881 XChangeGC( DISP, XX-> gc, GCJoinStyle, &gcv);
1882 XCHECKPOINT;
1883 } else {
1884 XX-> gcv. join_style = join;
1885 }
1886 return true;
1887 }
1888
1889 Bool
apc_gp_set_line_width(Handle self,float line_width)1890 apc_gp_set_line_width( Handle self, float line_width)
1891 {
1892 DEFXX;
1893 XGCValues gcv;
1894
1895 if ( XF_IN_PAINT(XX)) {
1896 XX-> paint_line_width = line_width;
1897 gcv. line_width = line_width +.5;
1898 if ( !( XX-> paint_ndashes == 0 || (XX-> paint_ndashes == 1 && XX-> paint_dashes[0] == 1))) {
1899 dDASH_FIX( line_width, XX-> paint_dashes, XX-> paint_ndashes);
1900 DASH_FIX;
1901 XSetDashes( DISP, XX-> gc, 0, DASHES);
1902 }
1903 XChangeGC( DISP, XX-> gc, GCLineWidth, &gcv);
1904 XCHECKPOINT;
1905 } else {
1906 XX-> gcv. line_width = line_width + .5;
1907 XX-> line_width = line_width;
1908 }
1909 return true;
1910 }
1911
1912 Bool
apc_gp_set_line_pattern(Handle self,unsigned char * pattern,int len)1913 apc_gp_set_line_pattern( Handle self, unsigned char *pattern, int len)
1914 {
1915 DEFXX;
1916 XGCValues gcv;
1917
1918 if ( XF_IN_PAINT(XX)) {
1919 if ( len == 0 || (len == 1 && pattern[0] == 1)) {
1920 gcv. line_style = LineSolid;
1921 XChangeGC( DISP, XX-> gc, GCLineStyle, &gcv);
1922 } else {
1923 dDASH_FIX(XX-> line_width, pattern, len);
1924 DASH_FIX;
1925 gcv. line_style = ( XX-> paint_rop2 == ropNoOper) ? LineOnOffDash : LineDoubleDash;
1926 XSetDashes( DISP, XX-> gc, 0, DASHES);
1927 XChangeGC( DISP, XX-> gc, GCLineStyle, &gcv);
1928 }
1929 XX-> line_style = gcv. line_style;
1930 free(XX->paint_dashes);
1931 if (( XX-> paint_dashes = malloc( len)))
1932 memcpy( XX-> paint_dashes, pattern, len);
1933 XX-> paint_ndashes = len;
1934 } else {
1935 free( XX-> dashes);
1936 if ( len == 0) { /* lpNull */
1937 XX-> dashes = NULL;
1938 XX-> ndashes = -1;
1939 XX-> gcv. line_style = LineSolid;
1940 } else if ( len == 1 && pattern[0] == 1) { /* lpSolid */
1941 XX-> dashes = NULL;
1942 XX-> ndashes = 0;
1943 XX-> gcv. line_style = LineSolid;
1944 } else { /* the rest */
1945 XX-> dashes = malloc( len);
1946 memcpy( XX-> dashes, pattern, len);
1947 XX-> ndashes = len;
1948 XX-> gcv. line_style = ( XX-> rop2 == ropNoOper) ? LineOnOffDash : LineDoubleDash;
1949 }
1950 }
1951 return true;
1952 }
1953
1954 Bool
apc_gp_set_miter_limit(Handle self,float miter_limit)1955 apc_gp_set_miter_limit( Handle self, float miter_limit)
1956 {
1957 DEFXX;
1958 if ( XF_IN_PAINT(XX)) return false;
1959 XX-> miter_limit = miter_limit;
1960 return true;
1961 }
1962
1963 Bool
apc_gp_set_rop(Handle self,int rop)1964 apc_gp_set_rop( Handle self, int rop)
1965 {
1966 DEFXX;
1967 int function;
1968
1969 if ( rop < 0 || rop >= sizeof( rop_map)/sizeof(int))
1970 function = GXnoop;
1971 else
1972 function = rop_map[ rop];
1973
1974 if ( XF_IN_PAINT(XX)) {
1975 if ( rop < 0 || rop >= sizeof( rop_map)/sizeof(int))
1976 rop = ropNoOper;
1977 XX-> paint_rop = rop;
1978 XSetFunction( DISP, XX-> gc, function);
1979 guts.xrender_pen_dirty = true;
1980 XCHECKPOINT;
1981 } else {
1982 XX-> gcv. function = function;
1983 XX-> rop = rop;
1984 }
1985 return true;
1986 }
1987
1988 Bool
apc_gp_set_rop2(Handle self,int rop)1989 apc_gp_set_rop2( Handle self, int rop)
1990 {
1991 DEFXX;
1992 if ( XF_IN_PAINT(XX)) {
1993 if ( XX-> paint_rop2 == rop) return true;
1994 XX-> paint_rop2 = ( rop == ropCopyPut) ? ropCopyPut : ropNoOper;
1995 if ( XX-> line_style != LineSolid) {
1996 XGCValues gcv;
1997 gcv. line_style = ( rop == ropCopyPut) ? LineDoubleDash : LineOnOffDash;
1998 XChangeGC( DISP, XX-> gc, GCLineStyle, &gcv);
1999 }
2000 guts.xrender_pen_dirty = true;
2001 } else {
2002 XX-> rop2 = rop;
2003 if ( XX-> gcv. line_style != LineSolid)
2004 XX-> gcv. line_style = ( rop == ropCopyPut) ? LineDoubleDash : LineOnOffDash;
2005 }
2006 return true;
2007 }
2008
2009 Bool
apc_gp_set_transform(Handle self,int x,int y)2010 apc_gp_set_transform( Handle self, int x, int y)
2011 {
2012 DEFXX;
2013 if ( XF_IN_PAINT(XX)) {
2014 XX-> gtransform. x = x;
2015 XX-> gtransform. y = y;
2016 } else {
2017 XX-> transform. x = x;
2018 XX-> transform. y = y;
2019 }
2020 return true;
2021 }
2022
2023 Bool
apc_gp_set_text_opaque(Handle self,Bool opaque)2024 apc_gp_set_text_opaque( Handle self, Bool opaque)
2025 {
2026 DEFXX;
2027 if ( XF_IN_PAINT(XX)) {
2028 XX-> flags. paint_opaque = !!opaque;
2029 } else {
2030 XX-> flags. opaque = !!opaque;
2031 }
2032 return true;
2033 }
2034
2035 Bool
apc_gp_set_text_out_baseline(Handle self,Bool baseline)2036 apc_gp_set_text_out_baseline( Handle self, Bool baseline)
2037 {
2038 DEFXX;
2039 if ( XF_IN_PAINT(XX)) {
2040 XX-> flags. paint_base_line = !!baseline;
2041 } else {
2042 XX-> flags. base_line = !!baseline;
2043 }
2044 return true;
2045 }
2046
2047 ApiHandle
apc_gp_get_handle(Handle self)2048 apc_gp_get_handle( Handle self)
2049 {
2050 return ( ApiHandle) X(self)-> gdrawable;
2051 }
2052
2053