1 #include "win32\win32guts.h"
2 #ifndef _APRICOT_H_
3 #include "apricot.h"
4 #endif
5 #include "guts.h"
6 #include "Window.h"
7 #include "Icon.h"
8 #include "DeviceBitmap.h"
9 
10 #ifdef __cplusplus
11 extern "C" {
12 #endif
13 
14 
15 #define  sys (( PDrawableData)(( PComponent) self)-> sysData)->
16 #define  dsys( view) (( PDrawableData)(( PComponent) view)-> sysData)->
17 #define var (( PWidget) self)->
18 #define HANDLE sys handle
19 #define DHANDLE(x) dsys(x) handle
20 
21 Bool
apc_gp_init(Handle self)22 apc_gp_init( Handle self)
23 {
24 	objCheck false;
25 	sys lineWidth = 1.0;
26 	return true;
27 }
28 
29 Bool
apc_gp_done(Handle self)30 apc_gp_done( Handle self)
31 {
32 	objCheck false;
33 	aa_free_arena(self, 0);
34 	if ( sys bm)
35 		if ( !DeleteObject( sys bm)) apiErr;
36 	if ( sys pal)
37 		if ( !DeleteObject( sys pal)) apiErr;
38 	if ( sys graphics) {
39 		GdipDeleteGraphics(sys graphics);
40 		sys graphics = NULL;
41 	}
42 	if ( sys ps) {
43 		if ( is_apt( aptWinPS) && is_apt( aptWM_PAINT)) {
44 			if ( !EndPaint(( HWND) var handle, &sys paintStruc)) apiErr;
45 		} else if ( is_apt( aptWinPS)) {
46 			if ( self == application)
47 				dc_free();
48 			else {
49 				if ( !ReleaseDC(( HWND) var handle,  sys ps)) apiErr;
50 			}
51 		}
52 	}
53 	if ( sys linePatternLen  > sizeof(sys linePattern)) free( sys linePattern);
54 	stylus_free( sys stylusResource, false); /* XXX check this */
55 	stylus_gp_free( sys stylusGPResource, false);
56 	if ( sys linePatternLen  > sizeof(sys linePattern)) free( sys linePattern);
57 	font_free( sys fontResource, false);
58 	if ( sys p256) free( sys p256);
59 	sys bm = NULL;
60 	sys pal = NULL;
61 	sys ps = NULL;
62 	sys bm = NULL;
63 	sys p256 = NULL;
64 	sys fontResource = NULL;
65 	sys stylusResource = NULL;
66 	sys stylusGPResource = NULL;
67 	sys linePattern = NULL;
68 	return true;
69 }
70 
71 #define ADJUST_LINE_END_DEF(typ)                                   \
72 void                                                               \
73 adjust_line_end_##typ                                              \
74 ( typ x1, typ y1, typ *x2, typ *y2)                                \
75 {                                                                  \
76 	if ( x1 == *x2)                                            \
77 		( y1 < *y2) ? ( *y2)++ : ( *y2)--;                 \
78 	else if ( y1 == *y2)                                       \
79 		( x1 < *x2) ? ( *x2)++ : ( *x2)--;                 \
80 	else {                                                     \
81 		long tan = ( *y2 - y1) * 1000L / ( *x2 - x1);      \
82 		if ( tan < 1000 && tan > -1000) {                  \
83 			typ dx = *x2 - x1;                         \
84 			( dx > 0) ? dx++ : dx--;                   \
85 			*x2 = x1 + dx;                             \
86 			*y2 = (typ)( y1 + dx * tan / 1000L);       \
87 		} else {                                           \
88 			typ dy = *y2 - y1;                         \
89 			( dy > 0) ? dy++ : dy--;                   \
90 			*x2 = (typ)( x1 + dy * 1000L / tan);       \
91 			*y2 = y1 + dy;                             \
92 		}                                                  \
93 	}                                                          \
94 }                                                                  \
95 
96 ADJUST_LINE_END_DEF(int);
97 ADJUST_LINE_END_DEF(LONG);
98 
99 static Bool
gp_Arc(Handle self,int nLeftRect,int nTopRect,int nRightRect,int nBottomRect,int nXRadial1,int nYRadial1,int nXRadial2,int nYRadial2,double angleStart,double angleEnd)100 gp_Arc(
101 	Handle self,
102 	int nLeftRect, int nTopRect, int nRightRect, int nBottomRect,
103 	int nXRadial1, int nYRadial1, int nXRadial2, int nYRadial2,
104 	double angleStart, double angleEnd
105 ) {
106 	if ( nXRadial1 == nXRadial2 && nYRadial1 == nYRadial2 && fabs(angleStart - angleEnd) < 360 ) {
107 		Bool ret;
108 		HGDIOBJ old;
109 
110 		old = SelectObject( sys ps, CreatePen( PS_SOLID, 1, sys stylus. brush. lb. lbColor));
111 		adjust_line_end_int( nXRadial1, nYRadial1, &nXRadial2, &nYRadial2);
112 		MoveToEx( sys ps, nXRadial1, nYRadial1, NULL);
113 		ret = LineTo( sys ps, nXRadial2, nYRadial2);
114 		DeleteObject(SelectObject( sys ps, old) );
115 		return ret;
116 	} else {
117 		return Arc(
118 			sys ps,
119 			nLeftRect,  nTopRect,  nRightRect,  nBottomRect,
120 			nXRadial1,  nYRadial1,  nXRadial2,  nYRadial2
121 		);
122 	}
123 }
124 
125 static Bool
gp_Chord(Handle self,int nLeftRect,int nTopRect,int nRightRect,int nBottomRect,int nXRadial1,int nYRadial1,int nXRadial2,int nYRadial2,double angleStart,double angleEnd,Bool filled)126 gp_Chord(
127   Handle self,
128   int nLeftRect, int nTopRect, int nRightRect, int nBottomRect,
129   int nXRadial1, int nYRadial1, int nXRadial2, int nYRadial2,
130   double angleStart, double angleEnd, Bool filled
131 ) {
132 	if (
133 		(abs(nXRadial1 - nXRadial2) < 2) &&
134 		(abs(nYRadial1 == nYRadial2) < 2) &&
135 		(fabs(angleStart - angleEnd) < 360 )
136 	) {
137 		Bool ret;
138 		HGDIOBJ old;
139 
140 		if ( filled ) {
141 			nXRadial2--;
142 			nYRadial2--;
143 		}
144 
145 		old = SelectObject( sys ps, CreatePen( PS_SOLID, 1, sys stylus. brush. lb. lbColor));
146 		adjust_line_end_int( nXRadial1, nYRadial1, &nXRadial2, &nYRadial2);
147 		MoveToEx( sys ps, nXRadial1, nYRadial1, NULL);
148 		ret = LineTo( sys ps, nXRadial2, nYRadial2);
149 		DeleteObject(SelectObject( sys ps, old) );
150 		return ret;
151 	} else {
152 		return Chord(
153 			sys ps,
154 			nLeftRect,  nTopRect,  nRightRect,  nBottomRect,
155 			nXRadial1,  nYRadial1,  nXRadial2,  nYRadial2
156 		);
157 	}
158 }
159 
160 static Bool
gp_Pie(Handle self,int nLeftRect,int nTopRect,int nRightRect,int nBottomRect,int nXRadial1,int nYRadial1,int nXRadial2,int nYRadial2,double angleStart,double angleEnd,Bool filled)161 gp_Pie(
162 	Handle self,
163 	int nLeftRect, int nTopRect, int nRightRect, int nBottomRect,
164 	int nXRadial1, int nYRadial1, int nXRadial2, int nYRadial2,
165 	double angleStart, double angleEnd, Bool filled
166 ) {
167 	if ( nXRadial1 == nXRadial2 && nYRadial1 == nYRadial2 && fabs(angleStart - angleEnd) < 360 ) {
168 		int cx, cy;
169 		Bool ret;
170 		HGDIOBJ old;
171 
172 		old = SelectObject( sys ps, CreatePen( PS_SOLID, 1, sys stylus. brush. lb. lbColor));
173 		cx  = ( nLeftRect + nRightRect ) / 2;
174 		cy  = ( nTopRect  + nBottomRect ) / 2;
175 		adjust_line_end_int( cx, cy, &nXRadial1, &nYRadial1);
176 		if ( filled ) {
177 			if ( nXRadial2 > cx ) nXRadial1 = nXRadial2;
178 			if ( nYRadial2 > cy ) nYRadial1 = nYRadial2;
179 		}
180 		MoveToEx( sys ps, cx, cy, NULL);
181 		ret = LineTo( sys ps, nXRadial1, nYRadial1);
182 		DeleteObject(SelectObject( sys ps, old) );
183 		return ret;
184 	} else {
185 		return Pie(
186 			sys ps,
187 			nLeftRect,  nTopRect,  nRightRect,  nBottomRect,
188 			nXRadial1,  nYRadial1,  nXRadial2,  nYRadial2
189 		);
190 	}
191 }
192 
193 
194 #define GRAD 57.29577951
195 
196 #define check_swap( parm1, parm2) if ( parm1 > parm2) { int parm3 = parm1; parm1 = parm2; parm2 = parm3;}
197 
198 #define ELLIPSE_RECT (int)(x - ( dX - 1) / 2), (int)(y - dY / 2), (int)(x + dX / 2 + 1), (int)(y + (dY - 1) / 2 + 1)
199 #define ELLIPSE_RECT_SUPERINCLUSIVE (int)(x - ( dX - 1) / 2), (int)(y - dY / 2), (int)(x + dX / 2 + 2), (int)(y + (dY - 1) / 2 + 2)
200 #define ARC_COMPLETE (int)(x + dX / 2 + 1), y, (int)(x + dX / 2 + 1), y
201 #define ARC_ANGLED   (int)(x + cos( angleStart / GRAD) * dX / 2 + 0.5), (int)(y - sin( angleStart / GRAD) * dY / 2 + 0.5), \
202 							(int)(x + cos( angleEnd / GRAD) * dX / 2 + 0.5),   (int)(y - sin( angleEnd / GRAD) * dY / 2 + 0.5)
203 #define ARC_ANGLED_SUPERINCLUSIVE   (int)(x + cos( angleStart / GRAD) * dX / 2 + 0.5), (int)(y - sin( angleStart / GRAD) * dY / 2 + 0.5), \
204 							(int)(x + cos( angleEnd / GRAD) * dX / 2 + 1.5),   (int)(y - sin( angleEnd / GRAD) * dY / 2 + 1.5)
205 
206 #define EMULATE_OPAQUE_LINE \
207 (sys stylus. pen. lopnStyle == PS_USERSTYLE && sys currentROP2 == ropCopyPut)
208 #define STYLUS_USE_OPAQUE_LINE \
209 	sys stylusFlags &=~ stbPen;\
210 	if ( !sys opaquePen) sys opaquePen = CreatePen( PS_SOLID, sys stylus.pen.lopnWidth.x, sys lbs[1]);\
211 	SelectObject(sys ps, sys opaquePen);\
212 	if (sys currentROP != R2_COPYPEN) SetROP2( sys ps, R2_COPYPEN)
213 #define STYLUS_RESTORE_OPAQUE_LINE if (sys currentROP != R2_COPYPEN) SetROP2( sys ps, sys currentROP)
214 
215 Bool
apc_gp_arc(Handle self,int x,int y,int dX,int dY,double angleStart,double angleEnd)216 apc_gp_arc( Handle self, int x, int y, int dX, int dY, double angleStart, double angleEnd)
217 { objCheck false; {
218 	int compl, needf;
219 	HDC ps = sys ps;
220 
221 	SHIFT_XY(x,y);
222 	compl = arc_completion( &angleStart, &angleEnd, &needf);
223 
224 	if (EMULATE_OPAQUE_LINE) {
225 		STYLUS_USE_OPAQUE_LINE;
226 		if ( compl )
227 			Arc( ps, ELLIPSE_RECT, ARC_COMPLETE);
228 		else
229 			gp_Arc( self, ELLIPSE_RECT, ARC_ANGLED, angleStart, angleEnd);
230 		STYLUS_RESTORE_OPAQUE_LINE;
231 	}
232 
233 	STYLUS_USE_PEN( ps);
234 	while( compl--)
235 		Arc( ps, ELLIPSE_RECT, ARC_COMPLETE);
236 	if ( !needf) return true;
237 	if ( !gp_Arc( self, ELLIPSE_RECT, ARC_ANGLED, angleStart, angleEnd)) apiErrRet;
238 	return true;
239 }}
240 
241 Bool
apc_gp_bar(Handle self,int x1,int y1,int x2,int y2)242 apc_gp_bar( Handle self, int x1, int y1, int x2, int y2)
243 {objCheck false;{
244 	HDC     ps = sys ps;
245 	HGDIOBJ old;
246 	Bool ok;
247 
248 	check_swap( x1, x2);
249 	check_swap( y1, y2);
250 	SHIFT_XY(x1,y1);
251 	SHIFT_XY(x2,y2);
252 
253 	ok = true;
254 	old = SelectObject( ps, hPenHollow);
255 	STYLUS_USE_BRUSH( ps);
256 
257 	if ( !( ok = Rectangle( ps, x1, y2, x2 + 2, y1 + 2)))
258 		apiErr;
259 	SelectObject( ps, old);
260 	return ok;
261 }}
262 
263 Bool
apc_gp_bars(Handle self,int nr,Rect * rr)264 apc_gp_bars( Handle self, int nr, Rect *rr)
265 {objCheck false;{
266 	HDC     ps = sys ps;
267 	HGDIOBJ old = SelectObject( ps, hPenHollow);
268 	Bool ok = true;
269 	int i;
270 	STYLUS_USE_BRUSH( ps);
271 	for ( i = 0; i < nr; i++, rr++) {
272 		Rect xr = *rr;
273 		check_swap( xr.left, xr.right);
274 		check_swap( xr.bottom, xr.top);
275 		SHIFT_XY( xr.left, xr.bottom);
276 		SHIFT_XY( xr.right, xr.top);
277 		if ( !( ok = Rectangle( ps, xr.left, xr.top, xr.left + 2, xr.bottom + 2))) {
278 			apiErr;
279 			break;
280 		}
281 	}
282 	SelectObject( ps, old);
283 	return ok;
284 }}
285 
286 Bool
apc_gp_alpha(Handle self,int alpha,int x1,int y1,int x2,int y2)287 apc_gp_alpha( Handle self, int alpha, int x1, int y1, int x2, int y2)
288 {objCheck false;{
289 	Bool ok;
290 	HDC dc, buf_dc;
291 	HBITMAP buf_bm, old_bm;
292 	unsigned int dst_lw, y, w, h;
293 	Byte *dst;
294 
295 	if ( !(
296 		(is_apt(aptDeviceBitmap) && ((PDeviceBitmap)self)->type == dbtLayered) ||
297 		is_apt(aptLayered) ||
298 		( apc_widget_get_layered_request(self) && apc_widget_surface_is_layered(self))
299 	))
300 	return false;
301 
302 	if ( x1 < 0 && y1 < 0 && x2 < 0 && y2 < 0) {
303 		x1 = y1 = 0;
304 		x2 = sys lastSize. x - 1;
305 		y2 = sys lastSize. y - 1;
306 	}
307 	check_swap( x1, x2);
308 	check_swap( y1, y2);
309 	w = x2 - x1 + 1;
310 	h = y2 - y1 + 1;
311 
312 	y1 = y2;
313 	SHIFT_XY(x1,y1);
314 
315 	dc     = GetDC(NULL);
316 	buf_dc = CreateCompatibleDC(dc);
317 	if ( !(buf_bm = image_create_argb_dib_section(dc, w, h, (uint32_t**) &dst))) {
318 		DeleteDC(buf_dc);
319 		ReleaseDC(NULL, dc);
320 		return false;
321 	}
322 
323 	old_bm = SelectObject(buf_dc, buf_bm);
324 	if ( !( ok = BitBlt( buf_dc, 0, 0, w, h, sys ps, x1, y1, SRCCOPY))) {
325 		apiErr;
326 		goto EXIT;
327 	}
328 
329 	dst_lw = w * 4;
330 	for ( y = 0; y < h; y++, dst += dst_lw ) {
331 		register Byte *dd = dst + 3;
332 		register unsigned int ww = w;
333 		while (ww--) {
334 			*dd = alpha;
335 			dd += 4;
336 		}
337 	}
338 
339 	if ( !( ok = BitBlt( sys ps, x1, y1, w, h, buf_dc, 0, 0, SRCCOPY)))
340 		apiErr;
341 
342 EXIT:
343 	SelectObject(buf_dc, old_bm);
344 	DeleteDC(buf_dc);
345 	DeleteObject(buf_bm);
346 	ReleaseDC(NULL, dc);
347 
348 	return ok;
349 }}
350 
351 Bool
apc_gp_can_draw_alpha(Handle self)352 apc_gp_can_draw_alpha( Handle self)
353 {
354 	objCheck false;
355 	if ( is_apt(aptDeviceBitmap))
356 		return ((PDeviceBitmap)self)->type != dbtBitmap;
357 	else if ( is_apt( aptImage ))
358 		return ((PImage)self)-> type != imBW;
359 	else
360 		return true;
361 }
362 
363 Bool
apc_gp_clear(Handle self,int x1,int y1,int x2,int y2)364 apc_gp_clear( Handle self, int x1, int y1, int x2, int y2)
365 {objCheck false;{
366 	Bool     ok = true;
367 	HDC      ps   = sys ps;
368 	HGDIOBJ  oldp = SelectObject( ps, hPenHollow);
369 	LOGBRUSH ers;
370 	HGDIOBJ  oldh;
371 	ers. lbStyle = PS_SOLID;
372 	ers. lbColor = sys lbs[ 1];
373 	ers. lbHatch = 0;
374 	oldh = CreateBrushIndirect( &ers);
375 	oldh = SelectObject( ps, oldh);
376 	if ( x1 < 0 && y1 < 0 && x2 < 0 && y2 < 0) {
377 		x1 = y1 = 0;
378 		x2 = sys lastSize. x - 1;
379 		y2 = sys lastSize. y - 1;
380 	}
381 	check_swap( x1, x2);
382 	check_swap( y1, y2);
383 	SHIFT_XY(x1,y1);
384 	SHIFT_XY(x2,y2);
385 	if ( !( ok = Rectangle( sys ps, x1, y2, x2 + 2, y1 + 2)))
386 		apiErr;
387 	SelectObject( ps, oldp);
388 	DeleteObject( SelectObject( ps, oldh));
389 	return ok;
390 }}
391 
392 Bool
apc_gp_chord(Handle self,int x,int y,int dX,int dY,double angleStart,double angleEnd)393 apc_gp_chord( Handle self, int x, int y, int dX, int dY, double angleStart, double angleEnd)
394 {objCheck false;{
395 	Bool ok = true;
396 	HDC     ps = sys ps;
397 	HGDIOBJ old = SelectObject( ps, hBrushHollow);
398 	int compl, needf;
399 	compl = arc_completion( &angleStart, &angleEnd, &needf);
400 
401 	SHIFT_XY(x,y);
402 
403 	if (EMULATE_OPAQUE_LINE) {
404 		STYLUS_USE_OPAQUE_LINE;
405 		if ( compl ) Arc( ps, ELLIPSE_RECT, ARC_COMPLETE);
406 		gp_Chord( self, ELLIPSE_RECT, ARC_ANGLED, angleStart, angleEnd, false);
407 		STYLUS_RESTORE_OPAQUE_LINE;
408 	}
409 
410 	STYLUS_USE_PEN( ps);
411 	while( compl--)
412 		Arc( ps, ELLIPSE_RECT, ARC_COMPLETE);
413 	if ( needf) {
414 		if ( !( ok = gp_Chord( self, ELLIPSE_RECT, ARC_ANGLED, angleStart, angleEnd, false))) apiErr;
415 	}
416 	SelectObject( ps, old);
417 	return ok;
418 }}
419 
420 Bool
apc_gp_draw_poly(Handle self,int numPts,Point * points)421 apc_gp_draw_poly( Handle self, int numPts, Point * points)
422 {objCheck false;{
423 	int i;
424 	POINT *p;
425 	Bool ok;
426 
427 	if ((p = malloc( sizeof(POINT) * numPts)) == NULL)
428 		return false;
429 
430 	for ( i = 0; i < numPts; i++)  {
431 		p[i].x = SHIFT_X(points[i].x);
432 		p[i].y = SHIFT_Y(points[i].y);
433 	}
434 	if ( p[0]. x != p[numPts - 1].x || p[0]. y != p[numPts - 1].y || numPts == 2)
435 		adjust_line_end_LONG( p[numPts - 2].x, p[numPts - 2].y, &p[numPts - 1].x, &p[numPts - 1].y);
436 
437 	if (EMULATE_OPAQUE_LINE) {
438 		STYLUS_USE_OPAQUE_LINE;
439 		Polyline( sys ps, p, numPts);
440 		STYLUS_RESTORE_OPAQUE_LINE;
441 	}
442 
443 	STYLUS_USE_PEN( sys ps);
444 	if ( !(ok = Polyline( sys ps, p, numPts))) apiErr;
445 
446 	free(p);
447 
448 	return ok;
449 }}
450 
451 Bool
apc_gp_draw_poly2(Handle self,int numPts,Point * points)452 apc_gp_draw_poly2( Handle self, int numPts, Point * points)
453 {objCheck false;{
454 	Bool ok = true;
455 	int i;
456 	DWORD * pts;
457 	POINT * p;
458 
459 	pts = ( DWORD *) malloc( sizeof( DWORD) * numPts);
460 	if ( !pts) return false;
461 	p = malloc( sizeof(POINT) * numPts);
462 	if ( !p ) {
463 		free(pts);
464 		return false;
465 	}
466 
467 	for ( i = 0; i < numPts; i++)  {
468 		p[i].x = SHIFT_X(points[i].x);
469 		p[i].y = SHIFT_Y(points[i].y);
470 		pts[i] = 2;
471 		if ( i & 1)
472 			adjust_line_end_LONG( p[i - 1].x, p[i - 1].y, &p[i].x, &p[i].y);
473 	}
474 
475 	if (EMULATE_OPAQUE_LINE) {
476 		STYLUS_USE_OPAQUE_LINE;
477 		PolyPolyline( sys ps, p, pts, numPts/2);
478 		STYLUS_RESTORE_OPAQUE_LINE;
479 	}
480 
481 	STYLUS_USE_PEN( sys ps);
482 	if ( !( ok = PolyPolyline( sys ps, p, pts, numPts/2))) apiErr;
483 	free( pts);
484 	free( p);
485 	return ok;
486 }}
487 
488 Bool
apc_gp_ellipse(Handle self,int x,int y,int dX,int dY)489 apc_gp_ellipse( Handle self, int x, int y, int dX, int dY)
490 {objCheck false;{
491 	Bool    ok = true;
492 	HDC     ps = sys ps;
493 	HGDIOBJ old = SelectObject( ps, hBrushHollow);
494 
495 	SHIFT_XY(x,y);
496 
497 	if (EMULATE_OPAQUE_LINE) {
498 		STYLUS_USE_OPAQUE_LINE;
499 		Ellipse( ps, ELLIPSE_RECT);
500 		STYLUS_RESTORE_OPAQUE_LINE;
501 	}
502 
503 	STYLUS_USE_PEN( ps);
504 	if ( !( ok = Ellipse( ps, ELLIPSE_RECT))) apiErr;
505 	SelectObject( ps, old);
506 	return ok;
507 }}
508 
509 Bool
apc_gp_fill_chord(Handle self,int x,int y,int dX,int dY,double angleStart,double angleEnd)510 apc_gp_fill_chord( Handle self, int x, int y, int dX, int dY, double angleStart, double angleEnd)
511 {objCheck false;{
512 	Bool ok = true;
513 	HDC     ps = sys ps;
514 	HGDIOBJ old;
515 	Bool   comp;
516 	int compl, needf;
517 
518 	compl = arc_completion( &angleStart, &angleEnd, &needf);
519 	comp = ((sys psFillMode & fmOverlay) == 0) || stylus_complex( &sys stylus, ps);
520 	SHIFT_XY(x,y);
521 	STYLUS_USE_BRUSH( ps);
522 
523 	if ( comp) {
524 		old  = SelectObject( ps, hPenHollow);
525 		while ( compl--)
526 			if ( !( ok = Ellipse( ps, ELLIPSE_RECT_SUPERINCLUSIVE))) apiErr;
527 		if ( !( ok = !needf || gp_Chord(
528 			self, ELLIPSE_RECT_SUPERINCLUSIVE, ARC_ANGLED_SUPERINCLUSIVE, angleStart, angleEnd, true
529 		))) apiErr;
530 	} else {
531 		old = SelectObject( ps, CreatePen( PS_SOLID, 1, sys stylus. brush. lb. lbColor));
532 		while ( compl--)
533 			if ( !( ok = Ellipse( ps, ELLIPSE_RECT))) apiErr;
534 		if ( !( ok = !needf || gp_Chord(
535 			self, ELLIPSE_RECT, ARC_ANGLED_SUPERINCLUSIVE, angleStart, angleEnd, true
536 		))) apiErr;
537 	}
538 	old = SelectObject( ps, old);
539 	if ( !comp) DeleteObject( old);
540 	return ok;
541 }}
542 
543 Bool
apc_gp_fill_ellipse(Handle self,int x,int y,int dX,int dY)544 apc_gp_fill_ellipse( Handle self, int x, int y, int dX, int dY)
545 {objCheck false;{
546 	Bool ok = true;
547 	HDC     ps  = sys ps;
548 	HGDIOBJ old;
549 	Bool    comp = ((sys psFillMode & fmOverlay) == 0) || stylus_complex( &sys stylus, ps);
550 	STYLUS_USE_BRUSH( ps);
551 	SHIFT_XY(x,y);
552 	if ( comp) {
553 		old  = SelectObject( ps, hPenHollow);
554 		if ( !( ok = Ellipse( ps, ELLIPSE_RECT_SUPERINCLUSIVE))) apiErr;
555 	} else {
556 		old = SelectObject( ps, CreatePen( PS_SOLID, 1, sys stylus. brush. lb. lbColor));
557 		if ( !( ok = Ellipse( ps, ELLIPSE_RECT))) apiErr;
558 	}
559 	old = SelectObject( ps, old);
560 	if ( !comp) DeleteObject( old);
561 	return ok;
562 }}
563 
564 static Handle ctx_R22R4[] = {
565 	R2_COPYPEN      ,  SRCCOPY          ,
566 	R2_XORPEN       ,  SRCINVERT        ,
567 	R2_MASKPEN      ,  SRCAND           ,
568 	R2_MERGEPEN     ,  SRCPAINT         ,
569 	R2_NOTCOPYPEN   ,  NOTSRCCOPY       ,
570 	R2_MASKPENNOT   ,  SRCERASE         ,
571 	R2_MERGEPENNOT  ,  0x00DD0228       ,
572 	R2_MASKNOTPEN   ,  0x00220326       ,
573 	R2_MERGENOTPEN  ,  MERGEPAINT       ,
574 	R2_NOTXORPEN    ,  0x00990066       ,
575 	R2_NOTMASKPEN   ,  0x007700E6       ,
576 	R2_NOTMERGEPEN  ,  NOTSRCERASE      ,
577 	R2_NOP          ,  0x00AA0029       ,
578 	R2_BLACK        ,  BLACKNESS        ,
579 	R2_WHITE        ,  WHITENESS        ,
580 	R2_NOT          ,  DSTINVERT        ,
581 	endCtx
582 };
583 
584 Bool
apc_gp_fill_poly(Handle self,int numPts,Point * points)585 apc_gp_fill_poly( Handle self, int numPts, Point * points)
586 {Bool ok = true; objCheck false;{
587 	HDC     ps = sys ps;
588 	int i;
589 	POINT *p;
590 
591 	if ((p = malloc( sizeof(POINT) * numPts)) == NULL)
592 		return false;
593 
594 	for ( i = 0; i < numPts; i++)  {
595 		p[i].x = SHIFT_X(points[i].x);
596 		p[i].y = SHIFT_Y(points[i].y);
597 	}
598 	if ( numPts == 2 )
599 		adjust_line_end_LONG( p[0].x, p[0].y, &p[1].x, &p[1].y);
600 
601 	if (( sys psFillMode & fmOverlay) == 0) {
602 		HGDIOBJ old = SelectObject( ps, hPenHollow);
603 		STYLUS_USE_BRUSH( ps);
604 		if ( !( ok = Polygon( ps, p, numPts))) apiErr;
605 		SelectObject( ps, old);
606 	} else if ( !stylus_complex( &sys stylus, ps)) {
607 		HPEN old = SelectObject( ps, CreatePen( PS_SOLID, 1, sys stylus. brush. lb. lbColor));
608 		STYLUS_USE_BRUSH( ps);
609 		if ( !( ok = Polygon( ps, p, numPts))) apiErr;
610 		DeleteObject( SelectObject( ps, old));
611 	} else {
612 		int dx       = sys lastSize.x;
613 		int dy       = sys lastSize.y;
614 		int rop      = ctx_remap_def( GetROP2( ps), ctx_R22R4, true, SRCCOPY);
615 		Point bound  = {0,0};
616 		Point trans;
617 		HBITMAP bmMask, bmSrc, bmJ;
618 		HDC dc;
619 		HGDIOBJ old1, oldelta;
620 		Bool db = is_apt( aptDeviceBitmap) || is_apt( aptBitmap);
621 		trans. x = dx;
622 		trans. y = dy;
623 		for ( i = 0; i < numPts; i++)  {
624 			if ( p[i].x > bound.x) bound.x = p[i].x;
625 			if ( p[i].y > bound.y) bound.y = p[i].y;
626 			if ( p[i].x < trans.x) trans.x = p[i].x;
627 			if ( p[i].y < trans.y) trans.y = p[i].y;
628 		}
629 		if (( trans. x == dx) || ( trans. y == dy)) {
630 			free(p);
631 			return false;
632 		}
633 		if ( bound. x > dx) bound. x = dx;
634 		if ( bound. y > dy) bound. y = dy;
635 		for ( i = 0; i < numPts; i++)  {
636 			p[i].x -= trans.x;
637 			p[i].y -= trans.y;
638 		}
639 		bound.x -= trans.x - 1;
640 		bound.y -= trans.y - 1;
641 
642 		if ( !( dc  = dc_compat_alloc( ps))) apiErrRet;
643 		if ( db) {
644 			if ( !( ps = dc_alloc())) { // fact that if dest ps is memory dc, CCB will result mono-bitmap
645 				dc_compat_free();
646 				free(p);
647 				return false;
648 			}
649 		}
650 		if ( !( bmSrc  = CreateCompatibleBitmap( ps, bound. x, bound. y))) {
651 			apiErr;
652 			if ( db) dc_free();
653 			dc_compat_free();
654 			free(p);
655 			return false;
656 		}
657 		if ( db) {
658 			dc_free();
659 			ps = sys ps;
660 		}
661 		if ( !( bmMask = CreateBitmap( bound. x, bound. y, 1, 1, NULL))) {
662 			apiErr;
663 			dc_compat_free();
664 			free(p);
665 			return false;
666 		}
667 		bmJ = SelectObject( dc, bmSrc);
668 		old1 = SelectObject( dc, sys stylusResource-> hbrush);
669 		oldelta = SelectObject( dc, hPenHollow);
670 		Rectangle( dc, 0, 0, bound. x + 1, bound. y + 1);
671 		SelectObject( dc, oldelta);
672 		SelectObject( dc, old1);
673 		SelectObject( dc, bmMask);
674 		SetROP2( dc, R2_WHITE);
675 		Rectangle( dc, 0, 0, bound. x, bound. y);
676 		SetROP2( dc, R2_BLACK);
677 		if ( !( ok = Polygon( dc, p, numPts))) apiErr;
678 		SelectObject( dc, bmSrc);
679 		if ( !( ok &= MaskBlt( ps, trans. x, trans. y, bound. x, bound. y, dc, 0, 0, bmMask, 0, 0,
680 					MAKEROP4( 0x00AA0029, rop)))) apiErr;
681 		SelectObject( dc, bmJ);
682 		dc_compat_free();
683 		DeleteObject( bmMask);
684 		DeleteObject( bmSrc);
685 	}
686 	free(p);
687 }return ok;}
688 
689 Bool
apc_gp_fill_sector(Handle self,int x,int y,int dX,int dY,double angleStart,double angleEnd)690 apc_gp_fill_sector( Handle self, int x, int y, int dX, int dY, double angleStart, double angleEnd)
691 {objCheck false;{
692 	Bool ok = true;
693 	HDC     ps = sys ps;
694 	HGDIOBJ old;
695 	POINT   pts[ 3];
696 	Bool comp;
697 	int compl, needf;
698 
699 	compl = arc_completion( &angleStart, &angleEnd, &needf);
700 	comp = ((sys psFillMode & fmOverlay) == 0) || stylus_complex( &sys stylus, ps);
701 
702 	SHIFT_XY(x,y);
703 	pts[0].x = x + cos( angleEnd   / GRAD) * dX / 2 + 0.5;
704 	pts[0].y = y - sin( angleEnd   / GRAD) * dY / 2 + 0.5;
705 	pts[1].x = x + cos( angleStart / GRAD) * dX / 2 + 0.5;
706 	pts[1].y = y - sin( angleStart / GRAD) * dY / 2 + 0.5;
707 
708 	STYLUS_USE_BRUSH( ps);
709 	if ( comp) {
710 		old = SelectObject( ps, hPenHollow);
711 		while ( compl--)
712 			if ( !( ok = Ellipse( ps, ELLIPSE_RECT_SUPERINCLUSIVE))) apiErr;
713 		if ( !( ok = !needf || gp_Pie(
714 			self, ELLIPSE_RECT_SUPERINCLUSIVE,
715 			pts[1].x, pts[1].y,
716 			pts[0].x, pts[0].y,
717 			angleStart, angleEnd, true
718 		))) apiErr;
719 	} else {
720 		old = SelectObject( ps, CreatePen( PS_SOLID, 1, sys stylus. brush. lb. lbColor));
721 		while ( compl--)
722 			if ( !( ok = Ellipse( ps, ELLIPSE_RECT))) apiErr;
723 		if ( !( ok = !needf || gp_Pie(
724 			self, ELLIPSE_RECT,
725 			pts[ 1]. x, pts[ 1]. y,
726 			pts[ 0]. x, pts[ 0]. y,
727 			angleStart, angleEnd, true
728 		))) apiErr;
729 	}
730 	old = SelectObject( ps, old);
731 	if ( !comp) DeleteObject( old);
732 	return ok;
733 }}
734 
735 Bool
apc_gp_flood_fill(Handle self,int x,int y,Color borderColor,Bool singleBorder)736 apc_gp_flood_fill( Handle self, int x, int y, Color borderColor, Bool singleBorder)
737 {objCheck false;{
738 	HDC ps = sys ps;
739 	STYLUS_USE_BRUSH( ps);
740 	SHIFT_XY(x,y);
741 	if ( !ExtFloodFill( ps, x, y, remap_color( borderColor, true),
742 		singleBorder ? FLOODFILLSURFACE : FLOODFILLBORDER)) apiErrRet;
743 	return true;
744 }}
745 
746 Color
apc_gp_get_pixel(Handle self,int x,int y)747 apc_gp_get_pixel( Handle self, int x, int y)
748 {objCheck clInvalid;{
749 	COLORREF c;
750 	SHIFT_XY(x,y);
751 	c = GetPixel( sys ps, x, y);
752 	if ( c == CLR_INVALID) return clInvalid;
753 	return remap_color(( Color) c, false);
754 }}
755 
756 ApiHandle
apc_gp_get_handle(Handle self)757 apc_gp_get_handle( Handle self)
758 {
759 	objCheck 0;
760 	return ( ApiHandle) sys ps;
761 }
762 
763 
764 Bool
apc_gp_line(Handle self,int x1,int y1,int x2,int y2)765 apc_gp_line( Handle self, int x1, int y1, int x2, int y2)
766 {objCheck false;{
767 	HDC ps = sys ps;
768 
769 	adjust_line_end_int( x1, y1, &x2, &y2);
770 	SHIFT_XY(x1,y1);
771 	SHIFT_XY(x2,y2);
772 
773 	if (EMULATE_OPAQUE_LINE) {
774 		STYLUS_USE_OPAQUE_LINE;
775 		MoveToEx( ps, x1, y1, NULL);
776 		LineTo( ps, x2, y2);
777 		STYLUS_RESTORE_OPAQUE_LINE;
778 	}
779 
780 	STYLUS_USE_PEN( ps);
781 
782 	MoveToEx( ps, x1, y1, NULL);
783 	if ( !LineTo( ps, x2, y2)) apiErrRet;
784 
785 	return true;
786 }}
787 
788 Bool
apc_gp_put_image(Handle self,Handle image,int x,int y,int xFrom,int yFrom,int xLen,int yLen,int rop)789 apc_gp_put_image( Handle self, Handle image, int x, int y, int xFrom, int yFrom, int xLen, int yLen, int rop)
790 {
791 	return apc_gp_stretch_image ( self, image, x, y, xFrom, yFrom, xLen, yLen, xLen, yLen, rop);
792 }
793 
794 Bool
apc_gp_rectangle(Handle self,int x1,int y1,int x2,int y2)795 apc_gp_rectangle( Handle self, int x1, int y1, int x2, int y2)
796 {objCheck false;{
797 	Bool ok = true;
798 	HDC     ps = sys ps;
799 	HGDIOBJ old;
800 
801 	check_swap( x1, x2);
802 	check_swap( y1, y2);
803 
804 	old = SelectObject( ps, hBrushHollow);
805 	if ( sys stylus. pen. lopnWidth. x > 1 &&
806 		(sys stylus. pen. lopnWidth. x % 2) == 0
807 		) {
808 		/* change up-winding to down-winding */
809 		y1--;
810 		y2--;
811 	}
812 	SHIFT_XY(x1,y1);
813 	SHIFT_XY(x2,y2);
814 
815 	if ( EMULATE_OPAQUE_LINE ) {
816 		STYLUS_USE_OPAQUE_LINE;
817 		Rectangle( sys ps, x1, y1 + 1, x2 + 1, y2);
818 		STYLUS_RESTORE_OPAQUE_LINE;
819 	}
820 
821 	STYLUS_USE_PEN( ps);
822 	if ( !( ok = Rectangle( sys ps, x1, y1 + 1, x2 + 1, y2))) apiErr;
823 	SelectObject( ps, old);
824 	return ok;
825 }}
826 
827 Bool
apc_gp_sector(Handle self,int x,int y,int dX,int dY,double angleStart,double angleEnd)828 apc_gp_sector( Handle self, int x, int y, int dX, int dY, double angleStart, double angleEnd)
829 {objCheck false;{
830 	Bool ok = true;
831 	HDC     ps = sys ps;
832 	int compl, needf;
833 	POINT   pts[ 2];
834 	HGDIOBJ old;
835 
836 	compl = arc_completion( &angleStart, &angleEnd, &needf);
837 	old = SelectObject( ps, hBrushHollow);
838 
839 	pts[0].x = x + cos(angleEnd   / GRAD) * dX / 2 + 0.5;
840 	pts[0].y = y - sin(angleEnd   / GRAD) * dY / 2 + 0.5;
841 	pts[1].x = x + cos(angleStart / GRAD) * dX / 2 + 0.5;
842 	pts[1].y = y - sin(angleStart / GRAD) * dY / 2 + 0.5;
843 
844 	SHIFT_XY(x,y);
845 
846 	if (EMULATE_OPAQUE_LINE) {
847 		STYLUS_USE_OPAQUE_LINE;
848 		if ( compl ) Arc( ps, ELLIPSE_RECT, ARC_COMPLETE);
849 		gp_Pie(
850 			self, ELLIPSE_RECT,
851 			pts[1].x, pts[1].y,
852 			pts[0].x, pts[0].y,
853 			angleStart, angleEnd, false
854 		);
855 		STYLUS_RESTORE_OPAQUE_LINE;
856 	}
857 
858 	STYLUS_USE_PEN( ps);
859 
860 	while( compl--)
861 		Arc( ps, ELLIPSE_RECT, ARC_COMPLETE);
862 	if ( needf) {
863 		if ( !( ok = gp_Pie(
864 			self, ELLIPSE_RECT,
865 			pts[1].x, pts[1].y,
866 			pts[0].x, pts[0].y,
867 			angleStart, angleEnd, false
868 		))) apiErr;
869 	}
870 
871 	SelectObject( ps, old);
872 	return ok;
873 }}
874 
875 Bool
apc_gp_set_pixel(Handle self,int x,int y,Color color)876 apc_gp_set_pixel( Handle self, int x, int y, Color color)
877 {
878 	objCheck false;
879 	SHIFT_XY(x,y);
880 	SetPixelV( sys ps, x, y, remap_color( color, true));
881 	return true;
882 }
883 
884 // gpi settings
885 Color
apc_gp_get_back_color(Handle self)886 apc_gp_get_back_color( Handle self)
887 {
888 	objCheck 0;
889 	return remap_color( sys lbs[1], false);
890 }
891 
892 int
apc_gp_get_bpp(Handle self)893 apc_gp_get_bpp( Handle self)
894 {
895 	objCheck 0;
896 	return sys bpp;
897 }
898 
899 Color
apc_gp_get_color(Handle self)900 apc_gp_get_color( Handle self)
901 {
902 	objCheck 0;
903 	return remap_color( sys ps ? sys stylus. pen. lopnColor : sys lbs[0], false);
904 }
905 
906 int
apc_gp_get_fill_mode(Handle self)907 apc_gp_get_fill_mode( Handle self)
908 {
909 	objCheck 0;
910 	return sys ps ? sys psFillMode : sys fillMode;
911 }
912 
913 static Handle ctx_le2PS_ENDCAP[] = {
914 	leRound,          PS_ENDCAP_ROUND             ,
915 	leSquare,         PS_ENDCAP_SQUARE            ,
916 	leFlat,           PS_ENDCAP_FLAT              ,
917 	endCtx
918 };
919 
920 int
apc_gp_get_line_end(Handle self)921 apc_gp_get_line_end( Handle self)
922 {
923 	objCheck 0;
924 	if ( !sys ps) return sys lineEnd;
925 	return ctx_remap_def( sys stylus. extPen. lineEnd, ctx_le2PS_ENDCAP, false, leRound);
926 }
927 
928 static Handle ctx_lj2PS_JOIN[] = {
929 	ljRound,          PS_JOIN_ROUND             ,
930 	ljBevel,          PS_JOIN_BEVEL             ,
931 	ljMiter,          PS_JOIN_MITER             ,
932 	endCtx
933 };
934 
935 int
apc_gp_get_line_join(Handle self)936 apc_gp_get_line_join( Handle self)
937 {
938 	objCheck 0;
939 	if ( !sys ps) return sys lineJoin;
940 	return ctx_remap_def( sys stylus. extPen. lineJoin, ctx_lj2PS_JOIN, false, ljRound);
941 }
942 
943 float
apc_gp_get_line_width(Handle self)944 apc_gp_get_line_width( Handle self)
945 {
946 	objCheck 0;
947 	return sys ps ? sys stylus.extPen.lineWidth : sys lineWidth;
948 }
949 
950 int
apc_gp_get_line_pattern(Handle self,unsigned char * buffer)951 apc_gp_get_line_pattern( Handle self, unsigned char * buffer)
952 {
953 	objCheck 0;
954 	if ( !sys ps) {
955 		memcpy(
956 			( char *) buffer,
957 			(char*)(( sys linePatternLen > sizeof(sys linePattern)) ? sys linePattern : (Byte*)(&sys linePattern)),
958 			sys linePatternLen
959 		);
960 		return sys linePatternLen;
961 	}
962 
963 	switch ( sys stylus. pen. lopnStyle) {
964 	case PS_NULL:
965 		strcpy(( char *) buffer, "");
966 		return 0;
967 	case PS_DASH:
968 		strcpy(( char *) buffer, psDash);
969 		return 2;
970 	case PS_DOT:
971 		strcpy(( char *) buffer, psDot);
972 		return 2;
973 	case PS_DASHDOT:
974 		strcpy(( char *) buffer, psDashDot);
975 		return 4;
976 	case PS_DASHDOTDOT:
977 		strcpy(( char *) buffer, psDashDotDot);
978 		return 6;
979 	case PS_USERSTYLE:
980 		{
981 			int i;
982 			int len = sys stylus. extPen. patResource-> dotsCount;
983 			if ( len > 255) len = 255;
984 			for ( i = 0; i < len; i++)
985 				buffer[ i] = sys stylus. extPen. patResource-> dots[ i];
986 			return len;
987 		}
988 	default:
989 		strcpy(( char *) buffer, "\1");
990 		return 1;
991 	}
992 }
993 
994 float
apc_gp_get_miter_limit(Handle self)995 apc_gp_get_miter_limit( Handle self)
996 {
997 	FLOAT ml;
998 	objCheck 0;
999 	if ( !sys ps) return sys miterLimit;
1000 	if (! GetMiterLimit( sys ps, &ml)) return 0;
1001 	return (float)ml;
1002 }
1003 
1004 Color
apc_gp_get_nearest_color(Handle self,Color color)1005 apc_gp_get_nearest_color( Handle self, Color color)
1006 {
1007 #define quit return remap_color( GetNearestColor( sys ps, clr), false)
1008 
1009 	XLOGPALETTE lpLoc, lpGlob;
1010 	int locIdx, globIdx, cdiff;
1011 	long clrGlob, clr = remap_color( color, true);
1012 	objCheck 0;
1013 
1014 	if ( !sys pal || ( sys bpp > 8)) quit;
1015 	lpLoc. palNumEntries = GetPaletteEntries( sys pal, 0, 256, lpLoc. palPalEntry);
1016 	if ( lpLoc. palNumEntries == 0)  quit;
1017 	lpGlob. palNumEntries = GetSystemPaletteEntries( sys ps, 0, 256, lpGlob. palPalEntry);
1018 	if ( lpGlob. palNumEntries == 0) quit;
1019 
1020 	locIdx = palette_match_color( &lpLoc, clr, &cdiff);
1021 	if ( cdiff >= COLOR_TOLERANCE)   quit;
1022 
1023 	clrGlob = ARGB(
1024 		lpLoc. palPalEntry[ locIdx]. peBlue,
1025 		lpLoc. palPalEntry[ locIdx]. peGreen,
1026 		lpLoc. palPalEntry[ locIdx]. peRed
1027 	);
1028 	globIdx = palette_match_color( &lpGlob, clrGlob, &cdiff);
1029 	if ( cdiff >= COLOR_TOLERANCE)   quit;
1030 	return ARGB(
1031 		lpGlob. palPalEntry[ globIdx]. peRed,
1032 		lpGlob. palPalEntry[ globIdx]. peGreen,
1033 		lpGlob. palPalEntry[ globIdx]. peBlue
1034 	);
1035 #undef quit
1036 }
1037 
1038 PRGBColor
apc_gp_get_physical_palette(Handle self,int * color)1039 apc_gp_get_physical_palette( Handle self, int * color)
1040 {
1041 	XLOGPALETTE lpGlob;
1042 	int i, nCol;
1043 	PRGBColor r;
1044 
1045 	*color = 0;
1046 	objCheck NULL;
1047 
1048 	if (( GetDeviceCaps( sys ps, RASTERCAPS) & RC_PALETTE) == 0)
1049 		return NULL;
1050 
1051 	nCol = GetDeviceCaps( sys ps, NUMCOLORS);
1052 	if ( nCol <= 0 || nCol > 256)
1053 		return NULL;
1054 
1055 
1056 	if ( sys pal && ( nCol > 16)) {
1057 		XLOGPALETTE lp;
1058 		int i, lpCount = 0;
1059 		int map[ 256];
1060 
1061 		lp. palNumEntries = GetPaletteEntries( sys pal, 0, 256, lp. palPalEntry);
1062 		lpGlob. palNumEntries = GetSystemPaletteEntries( sys ps, 0, 256, lpGlob. palPalEntry);
1063 
1064 		for ( i = 0; i < lp. palNumEntries; i++) {
1065 			long clr = ARGB(
1066 			lp. palPalEntry[ i]. peBlue,
1067 			lp. palPalEntry[ i]. peGreen,
1068 			lp. palPalEntry[ i]. peRed
1069 			);
1070 			int j, cdiff;
1071 			int idx = palette_match_color( &lpGlob, clr, &cdiff);
1072 			Bool hasmatch = 0;
1073 
1074 			if ( cdiff >= COLOR_TOLERANCE) continue;
1075 
1076 			if ( idx < 10 || idx > 245) continue;
1077 
1078 			for ( j = 0; j < lpCount; j++)
1079 				if ( map[ j] == idx) {
1080 					hasmatch = 1;
1081 					break;
1082 				}
1083 			if ( hasmatch) continue;
1084 			map[ lpCount++] = idx;
1085 		}
1086 
1087 		for ( i = 0; i < lpCount; i++)
1088 			lp. palPalEntry[ i] = lpGlob. palPalEntry[ map[ i]];
1089 		for ( i = 0; i < lpCount; i++)
1090 			lpGlob. palPalEntry[ i + nCol] = lp. palPalEntry[ i];
1091 		*color = nCol + lpCount;
1092 	} else {
1093 		*color = GetSystemPaletteEntries( sys ps, 0, 256, lpGlob. palPalEntry);
1094 		if (( nCol == 20) && ( *color == 256))
1095 			*color = 20;
1096 	}
1097 
1098 	if ( nCol == 20) {
1099 		int i;
1100 		for ( i = 0; i < 10; i++)
1101 			lpGlob. palPalEntry[ i + 10] = lpGlob. palPalEntry[ 255 - i];
1102 	}
1103 
1104 	r = ( PRGBColor) malloc( sizeof( RGBColor) * *color);
1105 	if ( !r) return NULL;
1106 
1107 	for ( i = 0; i < *color; i++) {
1108 		r[i].r = lpGlob. palPalEntry[i]. peRed;
1109 		r[i].g = lpGlob. palPalEntry[i]. peGreen;
1110 		r[i].b = lpGlob. palPalEntry[i]. peBlue;
1111 	}
1112 	return r;
1113 }
1114 
1115 Point
apc_gp_get_resolution(Handle self)1116 apc_gp_get_resolution( Handle self)
1117 {
1118 	Point p = guts. displayResolution;
1119 	if ( !self) return p;
1120 	objCheck p;
1121 	return is_apt( aptPrinter ) ? sys res : p;
1122 }
1123 
1124 static Handle ctx_rop2R2[] = {
1125 	ropCopyPut       , R2_COPYPEN      ,
1126 	ropXorPut        , R2_XORPEN       ,
1127 	ropAndPut        , R2_MASKPEN      ,
1128 	ropOrPut         , R2_MERGEPEN     ,
1129 	ropNotPut        , R2_NOTCOPYPEN   ,
1130 	ropNotDestAnd    , R2_MASKPENNOT   ,
1131 	ropNotDestOr     , R2_MERGEPENNOT  ,
1132 	ropNotSrcAnd     , R2_MASKNOTPEN   ,
1133 	ropNotSrcOr      , R2_MERGENOTPEN  ,
1134 	ropNotXor        , R2_NOTXORPEN    ,
1135 	ropNotAnd        , R2_NOTMASKPEN   ,
1136 	ropNotOr         , R2_NOTMERGEPEN  ,
1137 	ropNoOper        , R2_NOP          ,
1138 	ropBlackness     , R2_BLACK        ,
1139 	ropWhiteness     , R2_WHITE        ,
1140 	ropInvert        , R2_NOT          ,
1141 	endCtx
1142 };
1143 
1144 
1145 int
apc_gp_get_rop(Handle self)1146 apc_gp_get_rop( Handle self)
1147 {
1148 	objCheck 0;
1149 	if ( !sys ps) return sys rop;
1150 	return ctx_remap_def( GetROP2( sys ps), ctx_rop2R2, false, ropCopyPut);
1151 }
1152 
1153 int
apc_gp_get_rop2(Handle self)1154 apc_gp_get_rop2( Handle self)
1155 {
1156 	objCheck 0;
1157 	if ( !sys ps) return sys rop2;
1158 	return ( GetBkMode( sys ps) == OPAQUE) ? ropCopyPut : ropNoOper;
1159 }
1160 
1161 Point
apc_gp_get_transform(Handle self)1162 apc_gp_get_transform( Handle self)
1163 {
1164 	Point p = {0,0};
1165 	objCheck p;
1166 	if ( !sys ps) return sys transform;
1167 	p = sys gp_transform;
1168 	p. y = -p. y;
1169 	p. x += sys transform2. x;
1170 	p. y -= sys transform2. y;
1171 	return p;
1172 }
1173 
1174 #define pal_ok ((sys bpp <= 8) && ( sys pal))
1175 
1176 Bool
apc_gp_set_back_color(Handle self,Color color)1177 apc_gp_set_back_color( Handle self, Color color)
1178 {
1179 	long clr = remap_color( color, true);
1180 	objCheck false;
1181 	if ( sys ps) {
1182 		PStylus s = & sys stylus;
1183 		if ( pal_ok) clr = palette_match( self, clr);
1184 		if ( SetBkColor( sys ps, clr) == CLR_INVALID) apiErr;
1185 		s-> brush. backColor = clr;
1186 		if ( s-> brush. lb. lbStyle == BS_DIBPATTERNPT)
1187 			stylus_change( self);
1188 		if ( sys opaquePen ) {
1189 			sys stylusFlags &=~ stbPen;
1190 			SelectObject( sys ps, sys stockPen);
1191 			DeleteObject( sys opaquePen );
1192 			sys opaquePen = NULL;
1193 		}
1194 	}
1195 	sys lbs[1] = clr;
1196 	return true;
1197 }
1198 
1199 Bool
apc_gp_set_color(Handle self,Color color)1200 apc_gp_set_color( Handle self, Color color)
1201 {
1202 	long clr = remap_color( color, true);
1203 	objCheck false;
1204 	sys lbs[0] = clr;
1205 	if ( sys ps) {
1206 		PStylus s = & sys stylus;
1207 		if ( pal_ok) clr = palette_match( self, clr);
1208 		s-> pen. lopnColor = ( COLORREF) clr;
1209 		if ( s-> brush. lb. lbStyle != BS_DIBPATTERNPT)
1210 			s-> brush. lb. lbColor = ( COLORREF) clr;
1211 		stylus_change( self);
1212 		if ( sys alphaArenaPalette ) {
1213 			free(sys alphaArenaPalette);
1214 			sys alphaArenaPalette = NULL;
1215 		}
1216 	}
1217 	return true;
1218 }
1219 
1220 Bool
apc_gp_set_fill_mode(Handle self,int fillMode)1221 apc_gp_set_fill_mode( Handle self, int fillMode)
1222 {
1223 	objCheck false;
1224 	if ( sys ps) {
1225 		SetPolyFillMode( sys ps, ((fillMode & fmWinding) == fmAlternate) ? ALTERNATE : WINDING);
1226 		sys psFillMode = fillMode;
1227 	} else
1228 		sys fillMode = fillMode;
1229 	return true;
1230 }
1231 
1232 Bool
apc_gp_set_fill_pattern(Handle self,FillPattern pattern)1233 apc_gp_set_fill_pattern( Handle self, FillPattern pattern)
1234 {
1235 	objCheck false;
1236 {
1237 	HDC ps    = sys ps;
1238 	PStylus s = & sys stylus;
1239 	uint32_t *p1 = ( uint32_t*) pattern;
1240 	uint32_t *p2 = p1 + 1;
1241 	if ( !ps) {
1242 		memcpy( &sys fillPattern2, pattern, sizeof( FillPattern));
1243 		return true;
1244 	}
1245 	memcpy( &sys fillPattern, pattern, sizeof( FillPattern));
1246 	if (( *p1 == 0) && ( *p2 == 0)) {
1247 		s-> brush. lb. lbStyle = BS_SOLID;
1248 		s-> brush. lb. lbColor = GetBkColor( ps);
1249 		s-> brush. lb. lbHatch = 0;
1250 		s-> brush. backColor   = 0;
1251 		memset( s-> brush. pattern, 0, sizeof( s-> brush. pattern));
1252 	} else if (( *p1 == 0xFFFFFFFF) && ( *p2 == 0xFFFFFFFF)) {
1253 		s-> brush. lb. lbStyle = BS_SOLID;
1254 		s-> brush. lb. lbColor = s-> pen. lopnColor;
1255 		s-> brush. lb. lbHatch = 0;
1256 		s-> brush. backColor   = 0;
1257 		memset( s-> brush. pattern, 0, sizeof( s-> brush. pattern));
1258 	} else {
1259 		s-> brush. lb. lbStyle = BS_DIBPATTERNPT;
1260 		s-> brush. lb. lbColor = DIB_RGB_COLORS;
1261 		s-> brush. lb. lbHatch = ( LONG_PTR) &bmiHatch;
1262 		s-> brush. backColor   = GetBkColor( ps);
1263 		memcpy( s-> brush. pattern, pattern, sizeof( FillPattern));
1264 	}
1265 	stylus_change( self);
1266 	return true;
1267 }}
1268 
1269 Bool
apc_gp_set_fill_pattern_offset(Handle self,Point offset)1270 apc_gp_set_fill_pattern_offset( Handle self, Point offset)
1271 {
1272 	objCheck false;
1273 	if ( sys ps)
1274 		SetBrushOrgEx( sys ps, offset.x, 8 - offset.y, NULL);
1275 	else
1276 		sys fillPatternOffset = offset;
1277 	return true;
1278 }
1279 
1280 Bool
apc_gp_set_font(Handle self,PFont font)1281 apc_gp_set_font( Handle self, PFont font)
1282 {
1283 	OUTLINETEXTMETRICW otm;
1284 	objCheck false;
1285 	if ( !sys ps) return true;
1286 	font_change( self, font);
1287 
1288 	if ( GetOutlineTextMetricsW(sys ps, sizeof(otm), &otm)) {
1289 		sys tmOverhang             = otm.otmTextMetrics.tmOverhang;
1290 		sys tmPitchAndFamily       = otm.otmTextMetrics.tmPitchAndFamily;
1291 		sys otmsStrikeoutSize      = otm.otmsStrikeoutSize;
1292 		sys otmsStrikeoutPosition  = otm.otmsStrikeoutPosition;
1293 		sys otmsUnderscoreSize     = otm.otmsUnderscoreSize;
1294 		sys otmsUnderscorePosition = otm.otmsUnderscorePosition;
1295 	} else {
1296 		TEXTMETRICW tm;
1297 		GetTextMetricsW( sys ps, &tm);
1298 		sys tmOverhang        = tm.tmOverhang;
1299 		sys tmPitchAndFamily  = tm.tmPitchAndFamily;
1300 		sys otmsStrikeoutSize = sys otmsStrikeoutPosition = sys otmsUnderscoreSize = sys otmsUnderscorePosition = -1;
1301 	}
1302 
1303 	sys font_sin = sys font_cos = 0.0;
1304 
1305 	return true;
1306 }
1307 
1308 FillPattern *
apc_gp_get_fill_pattern(Handle self)1309 apc_gp_get_fill_pattern( Handle self)
1310 {
1311 	objCheck NULL;
1312 	return sys ps ? &sys fillPattern : &sys fillPattern2;
1313 }
1314 
1315 Point
apc_gp_get_fill_pattern_offset(Handle self)1316 apc_gp_get_fill_pattern_offset( Handle self)
1317 {
1318 	Point p = {0,0};
1319 	POINT wp;
1320 	objCheck p;
1321 	if ( !sys ps)
1322 		return sys fillPatternOffset;
1323 	GetBrushOrgEx( sys ps, &wp);
1324 	p. x = wp. x;
1325 	p. y = 8 - wp. y;
1326 	return p;
1327 }
1328 
1329 Bool
apc_gp_set_line_end(Handle self,int lineEnd)1330 apc_gp_set_line_end( Handle self, int lineEnd)
1331 {
1332 	objCheck false;
1333 	if ( !sys ps) {
1334 		sys lineEnd = lineEnd;
1335 	} else {
1336 		PStylus s         = &sys stylus;
1337 		PEXTPEN ep        = &s-> extPen;
1338 		ep-> lineEnd      = ctx_remap_def( lineEnd, ctx_le2PS_ENDCAP, true, PS_ENDCAP_ROUND);
1339 		if (( ep-> actual  = stylus_extpenned( s)))
1340 			ep-> style = stylus_get_extpen_style( s);
1341 		stylus_change( self);
1342 	}
1343 	return true;
1344 }
1345 
1346 Bool
apc_gp_set_line_join(Handle self,int lineJoin)1347 apc_gp_set_line_join( Handle self, int lineJoin)
1348 {
1349 	objCheck false;
1350 	if ( !sys ps) {
1351 		sys lineJoin = lineJoin;
1352 	} else {
1353 		PStylus s         = &sys stylus;
1354 		PEXTPEN ep        = &s-> extPen;
1355 		ep-> lineJoin     = ctx_remap_def( lineJoin, ctx_lj2PS_JOIN, true, PS_JOIN_ROUND);
1356 		if (( ep-> actual = stylus_extpenned( s)))
1357 			ep-> style = stylus_get_extpen_style( s);
1358 		stylus_change( self);
1359 	}
1360 	return true;
1361 }
1362 
1363 Bool
apc_gp_set_line_width(Handle self,float lineWidth)1364 apc_gp_set_line_width( Handle self, float lineWidth)
1365 {
1366 	objCheck false;
1367 	if ( !sys ps) {
1368 		sys lineWidth = lineWidth;
1369 	} else {
1370 		PStylus s = &sys stylus;
1371 		PEXTPEN ep        = &s-> extPen;
1372 		if ( lineWidth < 0.0 || lineWidth > 8192.0) lineWidth = 0.0;
1373 		s-> pen. lopnWidth. x = lineWidth + .5;
1374 		ep-> lineWidth = lineWidth;
1375 		if (( ep-> actual = stylus_extpenned( s)))
1376 			ep-> style = stylus_get_extpen_style( s);
1377 		stylus_change( self);
1378 	}
1379 	return true;
1380 }
1381 
1382 Bool
apc_gp_set_line_pattern(Handle self,unsigned char * pattern,int len)1383 apc_gp_set_line_pattern( Handle self, unsigned char * pattern, int len)
1384 {
1385 	objCheck false;
1386 	if ( !sys ps) {
1387 		if ( sys linePatternLen > sizeof(sys linePattern))
1388 			free( sys linePattern);
1389 		if ( len > sizeof(sys linePattern)) {
1390 			sys linePattern = ( unsigned char *) malloc( len);
1391 			if ( !sys linePattern) {
1392 				sys linePatternLen = 0;
1393 				return false;
1394 			}
1395 			memcpy( sys linePattern, pattern, len);
1396 		} else
1397 			memcpy( &sys linePattern, pattern, len);
1398 		sys linePatternLen = len;
1399 	} else {
1400 		PStylus s           = &sys stylus;
1401 		PEXTPEN ep          = &s-> extPen;
1402 
1403 		s-> pen. lopnStyle  = patres_user( pattern, len);
1404 		if (( ep-> actual    = stylus_extpenned( s))) {
1405 			ep-> style       = stylus_get_extpen_style( s);
1406 			ep-> patResource = ( s-> pen. lopnStyle == PS_USERSTYLE) ?
1407 				patres_fetch( pattern, len) : &hPatHollow;
1408 		} else
1409 			ep-> patResource = &hPatHollow;
1410 		stylus_change( self);
1411 	}
1412 	return true;
1413 }
1414 
1415 Bool
apc_gp_set_miter_limit(Handle self,float miter_limit)1416 apc_gp_set_miter_limit( Handle self, float miter_limit)
1417 {
1418 	objCheck false;
1419 	if ( !sys ps) {
1420 		sys miterLimit = miter_limit;
1421 		return true;
1422 	} else
1423 		return SetMiterLimit( sys ps, (FLOAT) miter_limit, NULL);
1424 }
1425 
1426 
1427 Bool
apc_gp_set_palette(Handle self)1428 apc_gp_set_palette( Handle self)
1429 {
1430 	HPALETTE pal;
1431 
1432 	objCheck false;
1433 	if ( sys p256) {
1434 		free( sys p256);
1435 		sys p256 = NULL;
1436 	}
1437 
1438 	pal = palette_create( self);
1439 	if ( sys ps) {
1440 		if ( pal)
1441 			SelectPalette( sys ps, pal, 0);
1442 		else
1443 			SelectPalette( sys ps, sys stockPalette, 1);
1444 		RealizePalette( sys ps);
1445 	}
1446 	if ( sys pal) DeleteObject( sys pal);
1447 	sys pal = pal;
1448 	return true;
1449 }
1450 
1451 Bool
apc_gp_set_rop(Handle self,int rop)1452 apc_gp_set_rop( Handle self, int rop)
1453 {
1454 	objCheck false;
1455 	if ( !sys ps) { sys rop = rop; return true; }
1456 	sys currentROP = ctx_remap_def( rop, ctx_rop2R2, true, R2_COPYPEN);
1457 	if ( !SetROP2( sys ps, sys currentROP)) apiErr;
1458 	return true;
1459 }
1460 
1461 Bool
apc_gp_set_rop2(Handle self,int rop)1462 apc_gp_set_rop2( Handle self, int rop)
1463 {
1464 	objCheck false;
1465 	if ( !sys ps) { sys rop2 = rop; return true; }
1466 	if ( rop != ropCopyPut) rop = ropNoOper;
1467 	sys currentROP2 = rop;
1468 	if ( !SetBkMode( sys ps, ( rop == ropCopyPut) ? OPAQUE : TRANSPARENT)) apiErr;
1469 	STYLUS_FREE_GP_BRUSH;
1470 	return true;
1471 }
1472 
1473 Bool
apc_gp_set_transform(Handle self,int x,int y)1474 apc_gp_set_transform( Handle self, int x, int y)
1475 {
1476 	objCheck false;
1477 	if ( !sys ps) {
1478 		sys transform. x = x;
1479 		sys transform. y = y;
1480 		return true;
1481 	}
1482 	sys gp_transform.x = x - sys transform2.x;
1483 	sys gp_transform.y = - ( y + sys transform2.y );
1484 	return true;
1485 }
1486 
1487 #ifdef __cplusplus
1488 }
1489 #endif
1490