1 /* $Id$ $Revision$ */
2 /* vim:set shiftwidth=4 ts=8: */
3
4 /*************************************************************************
5 * Copyright (c) 2011 AT&T Intellectual Property
6 * All rights reserved. This program and the accompanying materials
7 * are made available under the terms of the Eclipse Public License v1.0
8 * which accompanies this distribution, and is available at
9 * http://www.eclipse.org/legal/epl-v10.html
10 *
11 * Contributors: See CVS logs. Details at http://www.graphviz.org/
12 *************************************************************************/
13
14 /* Lefteris Koutsofios - AT&T Labs Research */
15
16 #include "common.h"
17 #include "g.h"
18 #include "gcommon.h"
19 #include "mem.h"
20
21 #define WPU widget->u.p
22 #define WINDOW widget->u.p->window
23 #define GC widget->u.p->gc
24
25 static long gstyles[5] = {
26 /* G_SOLID */ PS_SOLID,
27 /* G_DASHED */ PS_DASH,
28 /* G_DOTTED */ PS_DOT,
29 /* G_LONGDASHED */ PS_DASH,
30 /* G_SHORTDASHED */ PS_DASH,
31 };
32
33 static char grays[][4] = {
34 { 0x00, 0x00, 0x00, 0x00 },
35 { 0x08, 0x00, 0x00, 0x00 },
36 { 0x08, 0x00, 0x02, 0x00 },
37 { 0x0A, 0x00, 0x02, 0x00 },
38 { 0x0A, 0x00, 0x0A, 0x00 },
39 { 0x0A, 0x04, 0x0A, 0x00 },
40 { 0x0A, 0x04, 0x0A, 0x01 },
41 { 0x0A, 0x05, 0x0A, 0x01 },
42 { 0x0A, 0x05, 0x0A, 0x05 },
43 { 0x0E, 0x05, 0x0A, 0x05 },
44 { 0x0E, 0x05, 0x0B, 0x05 },
45 { 0x0F, 0x05, 0x0B, 0x05 },
46 { 0x0F, 0x05, 0x0F, 0x05 },
47 { 0x0F, 0x0D, 0x0F, 0x05 },
48 { 0x0F, 0x0D, 0x0F, 0x07 },
49 { 0x0F, 0x0F, 0x0F, 0x07 },
50 { 0x0F, 0x0F, 0x0F, 0x0F }
51 };
52
53 char *Gpscanvasname = "out.emf";
54
55 static void bezier (PIXpoint_t, PIXpoint_t, PIXpoint_t, PIXpoint_t);
56 static HFONT findfont (char *, int);
57 static int scalebitmap (Gwidget_t *, Gbitmap_t *, Gsize_t, int, int);
58 static void setgattr (Gwidget_t *, Ggattr_t *);
59
60 static PIXrect_t rdrawtopix (Gwidget_t *, Grect_t);
61 static PIXpoint_t pdrawtopix (Gwidget_t *, Gpoint_t);
62 static PIXsize_t sdrawtopix (Gwidget_t *, Gsize_t);
63 static PIXrect_t rdrawtobpix (Gbitmap_t *, Grect_t);
64 static PIXpoint_t pdrawtobpix (Gbitmap_t *, Gpoint_t);
65
GPcreatewidget(Gwidget_t * parent,Gwidget_t * widget,int attrn,Gwattr_t * attrp)66 int GPcreatewidget (
67 Gwidget_t *parent, Gwidget_t *widget, int attrn, Gwattr_t *attrp
68 ) {
69 PIXpoint_t po;
70 PIXsize_t ps;
71 PRINTDLG pd;
72 DOCINFO di;
73 DEVMODE *dmp;
74 /* the 2 here is to provide enough space for palPalEntry[0] and [1] */
75 LOGPALETTE pal[2];
76
77 HBRUSH brush;
78 HPEN pen;
79 HBITMAP bmap;
80 char *s, *s1;
81 int color, lflag, ai, dpix, dpiy, i;
82
83 s = Gpscanvasname;
84 lflag = FALSE;
85 po.x = po.y = 0;
86 ps.x = ps.y = MINPWSIZE;
87 for (ai = 0; ai < attrn; ai++) {
88 switch (attrp[ai].id) {
89 case G_ATTRORIGIN:
90 GETORIGIN (attrp[ai].u.p, po);
91 break;
92 case G_ATTRSIZE:
93 GETSIZE (attrp[ai].u.s, ps, MINPWSIZE);
94 break;
95 case G_ATTRNAME:
96 if (attrp[ai].u.t && attrp[ai].u.t[0])
97 s = attrp[ai].u.t;
98 break;
99 case G_ATTRMODE:
100 if (strcmp ("landscape", attrp[ai].u.t) == 0)
101 lflag = TRUE;
102 else if (strcmp ("portrait", attrp[ai].u.t) == 0)
103 lflag = FALSE;
104 else {
105 Gerr (POS, G_ERRBADATTRVALUE, attrp[ai].u.t);
106 return -1;
107 }
108 break;
109 case G_ATTRCOLOR:
110 /* will do it after the widget is created */
111 break;
112 case G_ATTRVIEWPORT:
113 /* will do it after the widget is created */
114 break;
115 case G_ATTRWINDOW:
116 /* will do it after the widget is created */
117 break;
118 case G_ATTRWINDOWID:
119 Gerr (POS, G_ERRCANNOTSETATTR1, "windowid");
120 return -1;
121 case G_ATTRUSERDATA:
122 widget->udata = attrp[ai].u.u;
123 break;
124 default:
125 Gerr (POS, G_ERRBADATTRID, attrp[ai].id);
126 return -1;
127 }
128 }
129 s1 = s + strlen (s) - 3;
130 if (s1 > s && strncmp (s1, "emf", 3) == 0) {
131 WPU->mode = 1;
132 ps.x *= 8.235, ps.y *= 8.235;
133 if (!(GC = CreateEnhMetaFile (NULL, s, NULL, "LEFTY\\0GRAPH\\0\\0"))) {
134 Gerr (POS, G_ERRCANNOTCREATEWIDGET);
135 return -1;
136 }
137 } else { /* open the printer device */
138 WPU->mode = 2;
139 di.cbSize = sizeof (DOCINFO);
140 di.lpszDocName = NULL;
141 di.lpszOutput = NULL;
142 di.lpszDatatype = "LEFTY";
143 di.fwType = 0;
144 pd.lStructSize = sizeof (pd);
145 pd.hwndOwner = NULL;
146 pd.hDevMode = NULL;
147 pd.hDevNames = NULL;
148 pd.hDC = NULL;
149 pd.Flags = PD_RETURNDC | PD_RETURNDEFAULT;
150 pd.nFromPage = 0;
151 pd.nToPage = 0;
152 pd.nMinPage = 0;
153 pd.nMaxPage = 0;
154 pd.nCopies = 1;
155 pd.hInstance = NULL;
156 pd.lCustData = NULL;
157 pd.lpfnPrintHook = NULL;
158 pd.lpfnSetupHook = NULL;
159 pd.lpPrintTemplateName = NULL;
160 pd.lpSetupTemplateName = NULL;
161 pd.hPrintTemplate = NULL;
162 pd.hSetupTemplate = NULL;
163 if (!PrintDlg (&pd)) {
164 Gerr (POS, G_ERRCANNOTCREATEWIDGET);
165 return -1;
166 }
167 if (lflag && pd.hDevMode) {
168 dmp = (DEVMODE *) GlobalLock (pd.hDevMode);
169 dmp->dmOrientation = DMORIENT_LANDSCAPE;
170 GlobalUnlock (pd.hDevMode);
171 pd.Flags = PD_RETURNDC;
172 if (!PrintDlg (&pd)) {
173 Gerr (POS, G_ERRCANNOTCREATEWIDGET);
174 return -1;
175 }
176 }
177 GC = pd.hDC;
178 dpix = GetDeviceCaps (GC, LOGPIXELSX);
179 if (dpix != 300)
180 ps.x = ps.x * (double) dpix / 300.0;
181 dpiy = GetDeviceCaps (GC, LOGPIXELSY);
182 if (dpiy != 300)
183 ps.y = ps.y * (double) dpiy / 300.0;
184 if (StartDoc (GC, &di) <= 0 || StartPage (GC) <= 0) {
185 Gerr (POS, G_ERRCANNOTCREATEWIDGET);
186 return -1;
187 }
188 }
189 WPU->wrect.o.x = 0.0, WPU->wrect.o.y = 0.0;
190 WPU->wrect.c.x = 1.0, WPU->wrect.c.y = 1.0;
191 WPU->vsize.x = ps.x, WPU->vsize.y = ps.y;
192 WPU->ncolor = 2;
193 pal[0].palVersion = 0x300; /* HA HA HA */
194 pal[0].palNumEntries = 2;
195 pal[0].palPalEntry[0].peRed = 255;
196 pal[0].palPalEntry[0].peGreen = 255;
197 pal[0].palPalEntry[0].peBlue = 255;
198 pal[0].palPalEntry[0].peFlags = 0;
199 pal[0].palPalEntry[1].peRed = 0;
200 pal[0].palPalEntry[1].peGreen = 0;
201 pal[0].palPalEntry[1].peBlue = 0;
202 pal[0].palPalEntry[1].peFlags = 0;
203 WPU->cmap = CreatePalette (&pal[0]);
204 WPU->colors[0].color = pal[0].palPalEntry[0];
205 for (i = 1; i < G_MAXCOLORS; i++)
206 WPU->colors[i].color = pal[0].palPalEntry[1];
207 SelectPalette (GC, WPU->cmap, FALSE);
208 RealizePalette (GC);
209 WPU->colors[0].inuse = TRUE;
210 WPU->colors[1].inuse = TRUE;
211 for (i = 2; i < G_MAXCOLORS; i++)
212 WPU->colors[i].inuse = FALSE;
213 WPU->gattr.color = 1;
214 brush = CreateSolidBrush (PALETTEINDEX (1));
215 SelectObject (GC, brush);
216 pen = CreatePen (PS_SOLID, 1, PALETTEINDEX (1));
217 SelectObject (GC, pen);
218 SetTextColor (GC, PALETTEINDEX (1));
219 SetBkMode (GC, TRANSPARENT);
220 WPU->gattr.width = 0;
221 WPU->gattr.mode = G_SRC;
222 WPU->gattr.fill = 0;
223 WPU->gattr.style = 0;
224 WPU->defgattr = WPU->gattr;
225 WPU->font = NULL;
226 if (Gdepth == 1) {
227 for (i = 0; i < 17; i++) {
228 if (!(bmap = CreateBitmap (4, 4, 1, 1, &grays[i][0])))
229 continue;
230 WPU->grays[i] = CreatePatternBrush (bmap);
231 }
232 }
233 for (ai = 0; ai < attrn; ai++) {
234 switch (attrp[ai].id) {
235 case G_ATTRCOLOR:
236 color = attrp[ai].u.c.index;
237 if (color < 0 || color > G_MAXCOLORS) {
238 Gerr (POS, G_ERRBADCOLORINDEX, color);
239 return -1;
240 }
241 WPU->colors[color].color.peRed = attrp[ai].u.c.r;
242 WPU->colors[color].color.peGreen = attrp[ai].u.c.g;
243 WPU->colors[color].color.peBlue = attrp[ai].u.c.b;
244 WPU->colors[color].color.peFlags = 0;
245 if (color >= WPU->ncolor)
246 ResizePalette (WPU->cmap, color + 1), WPU->ncolor = color + 1;
247 SetPaletteEntries (
248 WPU->cmap, (int) color, 1, &WPU->colors[color].color
249 );
250 RealizePalette (GC);
251 WPU->colors[color].inuse = TRUE;
252 if (color == WPU->gattr.color)
253 WPU->gattr.color = -1;
254 break;
255 case G_ATTRVIEWPORT:
256 if (attrp[ai].u.s.x == 0)
257 attrp[ai].u.s.x = 1;
258 if (attrp[ai].u.s.y == 0)
259 attrp[ai].u.s.y = 1;
260 WPU->vsize.x = attrp[ai].u.s.x + 0.5;
261 WPU->vsize.y = attrp[ai].u.s.y + 0.5;
262 SetWindowPos (
263 widget->w, (HWND) NULL, 0, 0, WPU->vsize.x,
264 WPU->vsize.y, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE
265 );
266 break;
267 case G_ATTRWINDOW:
268 if (attrp[ai].u.r.o.x == attrp[ai].u.r.c.x)
269 attrp[ai].u.r.c.x = attrp[ai].u.r.o.x + 1;
270 if (attrp[ai].u.r.o.y == attrp[ai].u.r.c.y)
271 attrp[ai].u.r.c.y = attrp[ai].u.r.o.y + 1;
272 WPU->wrect = attrp[ai].u.r;
273 break;
274 }
275 }
276 return 0;
277 }
278
GPsetwidgetattr(Gwidget_t * widget,int attrn,Gwattr_t * attrp)279 int GPsetwidgetattr (Gwidget_t *widget, int attrn, Gwattr_t *attrp) {
280 PIXsize_t ps;
281 int color, ai;
282
283 for (ai = 0; ai < attrn; ai++) {
284 switch (attrp[ai].id) {
285 case G_ATTRORIGIN:
286 break;
287 case G_ATTRSIZE:
288 break;
289 case G_ATTRNAME:
290 break;
291 case G_ATTRMODE:
292 break;
293 case G_ATTRCOLOR:
294 color = attrp[ai].u.c.index;
295 if (color < 0 || color > G_MAXCOLORS) {
296 Gerr (POS, G_ERRBADCOLORINDEX, color);
297 return -1;
298 }
299 WPU->colors[color].color.peRed = attrp[ai].u.c.r;
300 WPU->colors[color].color.peGreen = attrp[ai].u.c.g;
301 WPU->colors[color].color.peBlue = attrp[ai].u.c.b;
302 WPU->colors[color].color.peFlags = 0;
303 if (color >= WPU->ncolor)
304 ResizePalette (WPU->cmap, color + 1), WPU->ncolor = color + 1;
305 SetPaletteEntries (
306 WPU->cmap, (int) color, 1, &WPU->colors[color].color
307 );
308 RealizePalette (GC);
309 WPU->colors[color].inuse = TRUE;
310 if (color == WPU->gattr.color)
311 WPU->gattr.color = -1;
312 break;
313 case G_ATTRVIEWPORT:
314 if (attrp[ai].u.s.x == 0)
315 attrp[ai].u.s.x = 1;
316 if (attrp[ai].u.s.y == 0)
317 attrp[ai].u.s.y = 1;
318 WPU->vsize.x = attrp[ai].u.s.x + 0.5;
319 WPU->vsize.y = attrp[ai].u.s.y + 0.5;
320 ps.x = WPU->vsize.x, ps.y = WPU->vsize.y;
321 break;
322 case G_ATTRWINDOW:
323 if (attrp[ai].u.r.o.x == attrp[ai].u.r.c.x)
324 attrp[ai].u.r.c.x = attrp[ai].u.r.o.x + 1;
325 if (attrp[ai].u.r.o.y == attrp[ai].u.r.c.y)
326 attrp[ai].u.r.c.y = attrp[ai].u.r.o.y + 1;
327 WPU->wrect = attrp[ai].u.r;
328 break;
329 case G_ATTRWINDOWID:
330 Gerr (POS, G_ERRCANNOTSETATTR2, "windowid");
331 return -1;
332 case G_ATTRUSERDATA:
333 widget->udata = attrp[ai].u.u;
334 break;
335 default:
336 Gerr (POS, G_ERRBADATTRID, attrp[ai].id);
337 return -1;
338 }
339 }
340 return 0;
341 }
342
GPgetwidgetattr(Gwidget_t * widget,int attrn,Gwattr_t * attrp)343 int GPgetwidgetattr (Gwidget_t *widget, int attrn, Gwattr_t *attrp) {
344 PALETTEENTRY *cp;
345 int color, ai;
346
347 for (ai = 0; ai < attrn; ai++) {
348 switch (attrp[ai].id) {
349 case G_ATTRORIGIN:
350 break;
351 case G_ATTRSIZE:
352 break;
353 case G_ATTRNAME:
354 break;
355 case G_ATTRMODE:
356 break;
357 case G_ATTRCOLOR:
358 color = attrp[ai].u.c.index;
359 if (color < 0 || color > G_MAXCOLORS) {
360 Gerr (POS, G_ERRBADCOLORINDEX, color);
361 return -1;
362 }
363 if (WPU->colors[color].inuse) {
364 cp = &WPU->colors[color].color;
365 attrp[ai].u.c.r = cp->peRed;
366 attrp[ai].u.c.g = cp->peGreen;
367 attrp[ai].u.c.b = cp->peBlue;
368 } else {
369 attrp[ai].u.c.r = -1;
370 attrp[ai].u.c.g = -1;
371 attrp[ai].u.c.b = -1;
372 }
373 break;
374 case G_ATTRVIEWPORT:
375 attrp[ai].u.s = WPU->vsize;
376 break;
377 case G_ATTRWINDOW:
378 attrp[ai].u.r = WPU->wrect;
379 break;
380 case G_ATTRWINDOWID:
381 Gerr (POS, G_ERRCANNOTGETATTR, "windowid");
382 break;
383 case G_ATTRUSERDATA:
384 widget->udata = attrp[ai].u.u;
385 break;
386 default:
387 Gerr (POS, G_ERRBADATTRID, attrp[ai].id);
388 return -1;
389 }
390 }
391 return 0;
392 }
393
GPdestroywidget(Gwidget_t * widget)394 int GPdestroywidget (Gwidget_t *widget) {
395 HENHMETAFILE mfile;
396
397 if (WPU->mode == 1) {
398 mfile = CloseEnhMetaFile (GC);
399 OpenClipboard (NULL);
400 EmptyClipboard ();
401 SetClipboardData (CF_ENHMETAFILE, mfile);
402 CloseClipboard ();
403 DeleteMetaFile (mfile);
404 } else {
405 EndPage (GC);
406 EndDoc (GC);
407 }
408 return 0;
409 }
410
GPcanvasclear(Gwidget_t * widget)411 int GPcanvasclear (Gwidget_t *widget) {
412 HBRUSH brush, pbrush;
413
414 /* FIXME: drain repaint messages */
415 brush = CreateSolidBrush (PALETTEINDEX (0));
416 pbrush = SelectObject (GC, brush);
417 Rectangle (GC, 0, 0, (int) WPU->vsize.x, (int) WPU->vsize.y);
418 SelectObject (GC, pbrush);
419 return 0;
420 }
421
GPsetgfxattr(Gwidget_t * widget,Ggattr_t * ap)422 int GPsetgfxattr (Gwidget_t *widget, Ggattr_t *ap) {
423 setgattr (widget, ap);
424 WPU->defgattr = WPU->gattr;
425 return 0;
426 }
427
GPgetgfxattr(Gwidget_t * widget,Ggattr_t * ap)428 int GPgetgfxattr (Gwidget_t *widget, Ggattr_t *ap) {
429 if ((ap->flags & G_GATTRCOLOR))
430 ap->color = WPU->gattr.color;
431 if ((ap->flags & G_GATTRWIDTH))
432 ap->width = WPU->gattr.width;
433 if ((ap->flags & G_GATTRMODE))
434 ap->mode = WPU->gattr.mode;
435 if ((ap->flags & G_GATTRFILL))
436 ap->fill = WPU->gattr.fill;
437 if ((ap->flags & G_GATTRSTYLE))
438 ap->style = WPU->gattr.style;
439 return 0;
440 }
441
GParrow(Gwidget_t * widget,Gpoint_t gp1,Gpoint_t gp2,Ggattr_t * ap)442 int GParrow (Gwidget_t *widget, Gpoint_t gp1, Gpoint_t gp2, Ggattr_t *ap) {
443 PIXpoint_t pp1, pp2, pa, pb, pd;
444 double tangent, l;
445
446 pp1 = pdrawtopix (widget, gp1), pp2 = pdrawtopix (widget, gp2);
447 pd.x = pp1.x - pp2.x, pd.y = pp1.y - pp2.y;
448 if (pd.x == 0 && pd.y == 0)
449 return 0;
450 tangent = atan2 ((double) pd.y, (double) pd.x);
451 if ((l = sqrt ((double) (pd.x * pd.x + pd.y * pd.y))) > 30)
452 l = 30;
453 pa.x = l * cos (tangent + M_PI / 7) + pp2.x;
454 pa.y = l * sin (tangent + M_PI / 7) + pp2.y;
455 pb.x = l * cos (tangent - M_PI / 7) + pp2.x;
456 pb.y = l * sin (tangent - M_PI / 7) + pp2.y;
457 setgattr (widget, ap);
458 MoveToEx (GC, pp1.x, pp1.y, NULL), LineTo (GC, pp2.x, pp2.y);
459 MoveToEx (GC, pa.x, pa.y, NULL), LineTo (GC, pp2.x, pp2.y);
460 MoveToEx (GC, pb.x, pb.y, NULL), LineTo (GC, pp2.x, pp2.y);
461 return 0;
462 }
463
GPline(Gwidget_t * widget,Gpoint_t gp1,Gpoint_t gp2,Ggattr_t * ap)464 int GPline (Gwidget_t *widget, Gpoint_t gp1, Gpoint_t gp2, Ggattr_t *ap) {
465 PIXpoint_t pp1, pp2;
466
467 pp1 = pdrawtopix (widget, gp1), pp2 = pdrawtopix (widget, gp2);
468 setgattr (widget, ap);
469 MoveToEx (GC, pp1.x, pp1.y, NULL);
470 LineTo (GC, pp2.x, pp2.y);
471 return 0;
472 }
473
GPbox(Gwidget_t * widget,Grect_t gr,Ggattr_t * ap)474 int GPbox (Gwidget_t *widget, Grect_t gr, Ggattr_t *ap) {
475 PIXrect_t pr;
476 Grect_t gr2;
477
478 if (gr.o.x <= gr.c.x)
479 gr2.o.x = gr.o.x, gr2.c.x = gr.c.x;
480 else
481 gr2.o.x = gr.c.x, gr2.c.x = gr.o.x;
482 if (gr.o.y <= gr.c.y)
483 gr2.o.y = gr.o.y, gr2.c.y = gr.c.y;
484 else
485 gr2.o.y = gr.c.y, gr2.c.y = gr.o.y;
486 pr = rdrawtopix (widget, gr);
487 setgattr (widget, ap);
488 if (WPU->gattr.fill)
489 Rectangle (GC, pr.o.x, pr.o.y, pr.c.x, pr.c.y);
490 else {
491 Gppp[0].x = pr.o.x, Gppp[0].y = pr.o.y;
492 Gppp[1].x = pr.c.x, Gppp[1].y = pr.o.y;
493 Gppp[2].x = pr.c.x, Gppp[2].y = pr.c.y;
494 Gppp[3].x = pr.o.x, Gppp[3].y = pr.c.y;
495 Gppp[4].x = pr.o.x, Gppp[4].y = pr.o.y;
496 Polyline (GC, Gppp, 5);
497 }
498 return 0;
499 }
500
GPpolygon(Gwidget_t * widget,int gpn,Gpoint_t * gpp,Ggattr_t * ap)501 int GPpolygon (Gwidget_t *widget, int gpn, Gpoint_t *gpp, Ggattr_t *ap) {
502 int n, i;
503
504 if (gpn == 0)
505 return 0;
506 if (gpn + 1 > Gppn) {
507 n = (((gpn + 1) + PPINCR - 1) / PPINCR) * PPINCR;
508 Gppp = Marraygrow (Gppp, (long) n * PPSIZE);
509 Gppn = n;
510 }
511 for (i = 0; i < gpn; i++)
512 Gppp[i] = pdrawtopix (widget, gpp[i]);
513 setgattr (widget, ap);
514 if (WPU->gattr.fill) {
515 if (Gppp[gpn - 1].x != Gppp[0].x || Gppp[gpn - 1].y != Gppp[0].y)
516 Gppp[gpn] = Gppp[0], gpn++;
517 Polygon (GC, Gppp, (int) gpn);
518 } else
519 Polyline (GC, Gppp, (int) gpn);
520 return 0;
521 }
522
GPsplinegon(Gwidget_t * widget,int gpn,Gpoint_t * gpp,Ggattr_t * ap)523 int GPsplinegon (Gwidget_t *widget, int gpn, Gpoint_t *gpp, Ggattr_t *ap) {
524 PIXpoint_t p0, p1, p2, p3;
525 int n, i;
526
527 if (gpn == 0)
528 return 0;
529 Gppi = 1;
530 if (Gppi >= Gppn) {
531 n = (((Gppi + 1) + PPINCR - 1) / PPINCR) * PPINCR;
532 Gppp = Marraygrow (Gppp, (long) n * PPSIZE);
533 Gppn = n;
534 }
535 Gppp[0] = p3 = pdrawtopix (widget, gpp[0]);
536 for (i = 1; i < gpn; i += 3) {
537 p0 = p3;
538 p1 = pdrawtopix (widget, gpp[i]);
539 p2 = pdrawtopix (widget, gpp[i + 1]);
540 p3 = pdrawtopix (widget, gpp[i + 2]);
541 bezier (p0, p1, p2, p3);
542 }
543 setgattr (widget, ap);
544 if (WPU->gattr.fill) {
545 if (Gppp[Gppi - 1].x != Gppp[0].x || Gppp[Gppi - 1].y != Gppp[0].y)
546 Gppp[Gppi] = Gppp[0], Gppi++;
547 Polygon (GC, Gppp, (int) Gppi);
548 } else
549 Polyline (GC, Gppp, (int) Gppi);
550 return 0;
551 }
552
bezier(PIXpoint_t p0,PIXpoint_t p1,PIXpoint_t p2,PIXpoint_t p3)553 static void bezier (
554 PIXpoint_t p0, PIXpoint_t p1, PIXpoint_t p2, PIXpoint_t p3
555 ) {
556 Gpoint_t gp0, gp1, gp2;
557 Gsize_t s;
558 PIXpoint_t p;
559 double t;
560 int n, i, steps;
561
562 if ((s.x = p3.x - p0.x) < 0)
563 s.x = - s.x;
564 if ((s.y = p3.y - p0.y) < 0)
565 s.y = - s.y;
566 if (s.x > s.y)
567 steps = s.x / 5 + 1;
568 else
569 steps = s.y / 5 + 1;
570 for (i = 0; i <= steps; i++) {
571 t = i / (double) steps;
572 gp0.x = p0.x + t * (p1.x - p0.x);
573 gp0.y = p0.y + t * (p1.y - p0.y);
574 gp1.x = p1.x + t * (p2.x - p1.x);
575 gp1.y = p1.y + t * (p2.y - p1.y);
576 gp2.x = p2.x + t * (p3.x - p2.x);
577 gp2.y = p2.y + t * (p3.y - p2.y);
578 gp0.x = gp0.x + t * (gp1.x - gp0.x);
579 gp0.y = gp0.y + t * (gp1.y - gp0.y);
580 gp1.x = gp1.x + t * (gp2.x - gp1.x);
581 gp1.y = gp1.y + t * (gp2.y - gp1.y);
582 p.x = gp0.x + t * (gp1.x - gp0.x) + 0.5;
583 p.y = gp0.y + t * (gp1.y - gp0.y) + 0.5;
584 if (Gppi >= Gppn) {
585 n = (((Gppi + 1) + PPINCR - 1) / PPINCR) * PPINCR;
586 Gppp = Marraygrow (Gppp, (long) n * PPSIZE);
587 Gppn = n;
588 }
589 Gppp[Gppi++] = p;
590 }
591 }
592
GParc(Gwidget_t * widget,Gpoint_t gc,Gsize_t gs,double ang1,double ang2,Ggattr_t * ap)593 int GParc (
594 Gwidget_t *widget, Gpoint_t gc, Gsize_t gs,
595 double ang1, double ang2, Ggattr_t *ap
596 ) {
597 PIXpoint_t pc;
598 PIXsize_t ps;
599 double a1, a2;
600
601 pc = pdrawtopix (widget, gc), ps = sdrawtopix (widget, gs);
602 setgattr (widget, ap);
603 a1 = ang1 * M_PI / 180, a2 = ang2 * M_PI / 180;
604 if (WPU->gattr.fill)
605 Chord (
606 GC, pc.x - ps.x, pc.y - ps.y, pc.x + ps.x, pc.y + ps.y,
607 (int) (cos (a1) * ps.x), (int) (sin (a1) * ps.x),
608 (int) (cos (a2) * ps.x), (int) (sin (a2) * ps.x)
609 );
610 else
611 Arc (
612 GC, pc.x - ps.x, pc.y - ps.y, pc.x + ps.x, pc.y + ps.y,
613 (int) (cos (a1) * ps.x), (int) (sin (a1) * ps.x),
614 (int) (cos (a2) * ps.x), (int) (sin (a2) * ps.x)
615 );
616 return 0;
617 }
618
GPtext(Gwidget_t * widget,Gtextline_t * tlp,int n,Gpoint_t go,char * fn,double fs,char * justs,Ggattr_t * ap)619 int GPtext (
620 Gwidget_t *widget, Gtextline_t *tlp, int n, Gpoint_t go, char *fn,
621 double fs, char *justs, Ggattr_t *ap
622 ) {
623 Gsize_t gs;
624 PIXpoint_t po;
625 PIXsize_t ps;
626 PIXrect_t pr;
627 HFONT font;
628 SIZE size;
629 RECT r;
630 int x, y, w, h, i;
631
632 po = pdrawtopix (widget, go);
633 gs.x = 0, gs.y = fs;
634 ps = sdrawtopix (widget, gs);
635 if (!(font = findfont (fn, ps.y))) {
636 Rectangle (GC, po.x, po.y, po.x + 1, po.y + 1);
637 return 0;
638 }
639 setgattr (widget, ap);
640 if (font != WPU->font) {
641 WPU->font = font;
642 SelectObject (GC, font);
643 }
644 for (w = h = 0, i = 0; i < n; i++) {
645 if (tlp[i].n)
646 GetTextExtentPoint32 (GC, tlp[i].p, (int) tlp[i].n, &size);
647 else
648 GetTextExtentPoint32 (GC, "M", (int) 1, &size);
649 tlp[i].w = size.cx, tlp[i].h = size.cy;
650 w = max (w, size.cx), h += size.cy;
651 }
652 switch (justs[0]) {
653 case 'l': po.x += w / 2; break;
654 case 'r': po.x -= w / 2; break;
655 }
656 switch (justs[1]) {
657 case 'd': po.y -= h; break;
658 case 'c': po.y -= h / 2; break;
659 }
660 pr.o.x = po.x - w / 2, pr.o.y = po.y;
661 pr.c.x = po.x + w / 2, pr.c.y = po.y + h;
662 for (i = 0; i < n; i++) {
663 switch (tlp[i].j) {
664 case 'l': x = po.x - w / 2; break;
665 case 'n': x = po.x - tlp[i].w / 2; break;
666 case 'r': x = po.x - (tlp[i].w - w / 2); break;
667 }
668 y = po.y + i * tlp[i].h;
669 r.left = x, r.top = y;
670 r.right = x + tlp[i].w, r.bottom = y + tlp[i].h;
671 DrawText (GC, tlp[i].p, (int) tlp[i].n, &r, DT_LEFT | DT_TOP);
672 }
673 return 0;
674 }
675
findfont(char * name,int size)676 static HFONT findfont (char *name, int size) {
677 HFONT font;
678 int fi;
679
680 if (name[0] == '\000')
681 return Gfontp[0].font;
682
683 sprintf (&Gbufp[0], name, size);
684 for (fi = 0; fi < Gfontn; fi++)
685 if (strcmp (&Gbufp[0], Gfontp[fi].name) == 0 && Gfontp[fi].size == size)
686 return Gfontp[fi].font;
687 font = CreateFont (
688 (int) size, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, &Gbufp[0]
689 );
690 if (!font)
691 font = Gfontp[0].font;
692
693 Gfontp = Marraygrow (Gfontp, (long) (Gfontn + 1) * FONTSIZE);
694 Gfontp[Gfontn].name = strdup (&Gbufp[0]);
695 Gfontp[Gfontn].size = size;
696 Gfontp[Gfontn].font = font;
697 Gfontn++;
698 return font;
699 }
700
GPcreatebitmap(Gwidget_t * widget,Gbitmap_t * bitmap,Gsize_t s)701 int GPcreatebitmap (Gwidget_t *widget, Gbitmap_t *bitmap, Gsize_t s) {
702 if (!widget) {
703 Gerr (POS, G_ERRNOPARENTWIDGET);
704 return -1;
705 }
706 if (!bitmap) {
707 Gerr (POS, G_ERRNOBITMAP);
708 return -1;
709 }
710 if (!(bitmap->u.bmap.orig = CreateBitmap (
711 (int) s.x, (int) s.y, 1, Gdepth, NULL
712 ))) {
713 Gerr (POS, G_ERRCANNOTCREATEBITMAP);
714 return -1;
715 }
716 bitmap->u.bmap.scaled = 0;
717 bitmap->scale.x = bitmap->scale.y = 1;
718 bitmap->ctype = widget->type;
719 bitmap->canvas = widget - &Gwidgets[0];
720 bitmap->size = s;
721 return 0;
722 }
723
GPdestroybitmap(Gbitmap_t * bitmap)724 int GPdestroybitmap (Gbitmap_t *bitmap) {
725 if (!bitmap) {
726 Gerr (POS, G_ERRNOBITMAP);
727 return -1;
728 }
729 DeleteObject (bitmap->u.bmap.orig);
730 return 0;
731 }
732
GPreadbitmap(Gwidget_t * widget,Gbitmap_t * bitmap,FILE * fp)733 int GPreadbitmap (Gwidget_t *widget, Gbitmap_t *bitmap, FILE *fp) {
734 Gsize_t s;
735 HDC gc;
736 char bufp[2048];
737 unsigned int rgb[3];
738 char *s1, *s2;
739 char c;
740 int bufn, bufi, step, x, y, k;
741
742 if (!widget) {
743 Gerr (POS, G_ERRNOPARENTWIDGET);
744 return -1;
745 }
746 if (!bitmap) {
747 Gerr (POS, G_ERRNOBITMAP);
748 return -1;
749 }
750 step = 0;
751 while (step < 3) {
752 l1:
753 if (!fgets (bufp, 2048, fp)) {
754 Gerr (POS, G_ERRCANNOTREADBITMAP);
755 return -1;
756 }
757 s1 = &bufp[0];
758 l2:
759 for (; *s1 && isspace (*s1); s1++)
760 ;
761 if (!*s1 || *s1 == '#')
762 goto l1;
763 switch (step) {
764 case 0:
765 if (strncmp (s1, "P6", 2) != 0) {
766 Gerr (POS, G_ERRCANNOTREADBITMAP);
767 return -1;
768 }
769 step++, s1 += 2;
770 goto l2;
771 case 1:
772 for (s2 = s1; *s2 && *s2 >= '0' && *s2 <= '9'; s2++)
773 ;
774 c = *s2, *s2 = 0;
775 if (s2 == s1 || (s.x = atoi (s1)) <= 0) {
776 *s2 = c, Gerr (POS, G_ERRCANNOTREADBITMAP);
777 return -1;
778 }
779 *s2 = c, step++, s1 = s2;
780 goto l2;
781 case 2:
782 for (s2 = s1; *s2 && *s2 >= '0' && *s2 <= '9'; s2++)
783 ;
784 c = *s2, *s2 = 0;
785 if (s2 == s1 || (s.y = atoi (s1)) <= 0) {
786 *s2 = c, Gerr (POS, G_ERRCANNOTREADBITMAP);
787 return -1;
788 }
789 *s2 = c, step++, s1 = s2;
790 goto l2;
791 }
792 }
793 if (!(bitmap->u.bmap.orig = CreateBitmap (
794 (int) s.x, (int) s.y, 1, Gdepth, NULL
795 ))) {
796 Gerr (POS, G_ERRCANNOTCREATEBITMAP);
797 return -1;
798 }
799 gc = CreateCompatibleDC (GC);
800 SelectObject (gc, bitmap->u.bmap.orig);
801 bitmap->u.bmap.scaled = 0;
802 bitmap->scale.x = bitmap->scale.y = 1;
803 bitmap->ctype = widget->type;
804 bitmap->canvas = widget - &Gwidgets[0];
805 bitmap->size = s;
806 bufi = bufn = 0;
807 bufp[bufi] = 0;
808 for (y = 0; y < s.y; y++) {
809 for (x = 0; x < s.x; x++) {
810 for (k = 0; k < 3; k++) {
811 if (bufi == bufn) {
812 if ((bufn = fread (bufp, 1, 2047, fp)) == 0) {
813 if (ferror (fp))
814 bufn = -1;
815 DeleteDC (gc);
816 DeleteObject (bitmap->u.bmap.orig);
817 Gerr (POS, G_ERRCANNOTCREATEBITMAP);
818 return -1;
819 }
820 bufi = 0;
821 }
822 rgb[k] = (unsigned char) bufp[bufi++];
823 }
824 SetPixel (gc, x, y, RGB (rgb[0], rgb[1], rgb[2]));
825 }
826 }
827 DeleteDC (gc);
828 return 0;
829 }
830
GPwritebitmap(Gbitmap_t * bitmap,FILE * fp)831 int GPwritebitmap (Gbitmap_t *bitmap, FILE *fp) {
832 Gwidget_t *widget;
833 HDC gc;
834 COLORREF color;
835 char bufp[2048];
836 int bufi, x, y, w, h;
837
838 if (!bitmap) {
839 Gerr (POS, G_ERRNOBITMAP);
840 return -1;
841 }
842 if (
843 bitmap->canvas < 0 || bitmap->canvas >= Gwidgetn ||
844 !Gwidgets[bitmap->canvas].inuse
845 ) {
846 Gerr (POS, G_ERRBADWIDGETID, bitmap->canvas);
847 return -1;
848 }
849 widget = &Gwidgets[bitmap->canvas];
850 if (widget->type != G_CANVASWIDGET && widget->type != G_PCANVASWIDGET) {
851 Gerr (POS, G_ERRNOTACANVAS, bitmap->canvas);
852 return -1;
853 }
854 gc = CreateCompatibleDC (GC);
855 SelectObject (gc, bitmap->u.bmap.orig);
856 fprintf (fp, "P6\n%d %d 255\n", (int) bitmap->size.x, (int) bitmap->size.y);
857 bufi = 0;
858 w = bitmap->size.x;
859 h = bitmap->size.y;
860 for (y = 0; y < h; y++) {
861 for (x = 0; x < w; x++) {
862 color = GetPixel (gc, x, y);
863 bufp[bufi++] = GetRValue (color);
864 bufp[bufi++] = GetGValue (color);
865 bufp[bufi++] = GetBValue (color);
866 if (bufi + 3 >= 2048) {
867 fwrite (bufp, 1, bufi, fp);
868 bufi = 0;
869 }
870 }
871 }
872 if (bufi > 0)
873 fwrite (bufp, 1, bufi, fp);
874 DeleteDC (gc);
875 return 0;
876 }
877
GPbitblt(Gwidget_t * widget,Gpoint_t gp,Grect_t gr,Gbitmap_t * bitmap,char * mode,Ggattr_t * ap)878 int GPbitblt (
879 Gwidget_t *widget, Gpoint_t gp, Grect_t gr, Gbitmap_t *bitmap,
880 char *mode, Ggattr_t *ap
881 ) {
882 PIXrect_t pr, r;
883 PIXpoint_t pp;
884 PIXsize_t s;
885 Gsize_t scale;
886 Gxy_t p;
887 HBITMAP pix;
888 HDC gc;
889 double tvx, tvy, twx, twy;
890
891 if (gr.o.x > gr.c.x)
892 p.x = gr.o.x, gr.o.x = gr.c.x, gr.c.x = p.x;
893 if (gr.o.y > gr.c.y)
894 p.y = gr.o.y, gr.o.y = gr.c.y, gr.c.y = p.y;
895 if (strcmp (mode, "b2c") == 0) {
896 tvx = WPU->vsize.x, tvy = WPU->vsize.y;
897 twx = WPU->wrect.c.x - WPU->wrect.o.x;
898 twy = WPU->wrect.c.y - WPU->wrect.o.y;
899 scale.x = tvx / twx, scale.y = tvy / twy;
900 if (scale.x == 1 && scale.y == 1) {
901 pix = bitmap->u.bmap.orig;
902 bitmap->scale = scale;
903 } else {
904 if (scale.x != bitmap->scale.x || scale.y != bitmap->scale.y)
905 scalebitmap (widget, bitmap, scale, TRUE, 1);
906 pix = bitmap->u.bmap.scaled;
907 }
908 pr = rdrawtopix (widget, gr);
909 pp = pdrawtobpix (bitmap, gp);
910 s.x = pr.c.x - pr.o.x + 1, s.y = pr.c.y - pr.o.y + 1;
911 r.o.x = pp.x, r.o.y = pp.y - s.y + 1;
912 r.c.x = r.o.x + s.x - 1, r.c.y = r.o.y + s.y - 1;
913 if (r.o.x < 0)
914 pr.o.x -= r.o.x, r.o.x = 0;
915 if (r.o.y < 0)
916 pr.o.y -= r.o.y, r.o.y = 0;
917 if (r.c.x >= bitmap->size.x * scale.x) {
918 pr.c.x -= (r.c.x + 1 - bitmap->size.x * scale.x);
919 r.c.x = bitmap->size.x * scale.x - 1;
920 }
921 if (r.c.y >= bitmap->size.y * scale.y) {
922 pr.c.y -= (r.c.y + 1 - bitmap->size.y * scale.y);
923 r.c.y = bitmap->size.y * scale.y - 1;
924 }
925 if (pr.o.x < 0)
926 r.o.x -= pr.o.x, pr.o.x = 0;
927 if (pr.o.y < 0)
928 r.o.y -= pr.o.y, pr.o.y = 0;
929 setgattr (widget, ap);
930 gc = CreateCompatibleDC (GC);
931 SelectObject (gc, pix);
932 BitBlt (
933 GC, pr.o.x, pr.o.y, r.c.x - r.o.x + 1, r.c.y - r.o.y + 1,
934 gc, r.o.x, r.o.y, (WPU->gattr.mode == G_SRC) ? SRCCOPY : SRCINVERT
935 );
936 DeleteDC (gc);
937 } else if (strcmp (mode, "c2b") == 0) {
938 tvx = WPU->vsize.x, tvy = WPU->vsize.y;
939 twx = WPU->wrect.c.x - WPU->wrect.o.x;
940 twy = WPU->wrect.c.y - WPU->wrect.o.y;
941 scale.x = tvx / twx, scale.y = tvy / twy;
942 if (scale.x == 1 && scale.y == 1) {
943 pix = bitmap->u.bmap.orig;
944 bitmap->scale = scale;
945 } else {
946 if (scale.x != bitmap->scale.x || scale.y != bitmap->scale.y)
947 scalebitmap (widget, bitmap, scale, FALSE, 1);
948 pix = bitmap->u.bmap.scaled;
949 }
950 pr = rdrawtobpix (bitmap, gr);
951 pp = pdrawtopix (widget, gp);
952 s.x = pr.c.x - pr.o.x + 1, s.y = pr.c.y - pr.o.y + 1;
953 r.o.x = pp.x, r.o.y = pp.y - s.y + 1;
954 r.c.x = r.o.x + s.x - 1, r.c.y = r.o.y + s.y - 1;
955 if (pr.o.x < 0)
956 r.o.x -= pr.o.x, pr.o.x = 0;
957 if (pr.o.y < 0)
958 r.o.y -= pr.o.y, pr.o.y = 0;
959 if (pr.c.x >= bitmap->size.x * scale.x) {
960 r.c.x -= (pr.c.x + 1 - bitmap->size.x * scale.x);
961 pr.c.x = bitmap->size.x * scale.x - 1;
962 }
963 if (pr.c.y >= bitmap->size.y * scale.y) {
964 r.c.y -= (pr.c.y + 1 - bitmap->size.y * scale.y);
965 pr.c.y = bitmap->size.y * scale.y - 1;
966 }
967 if (r.o.x < 0)
968 pr.o.x -= r.o.x, r.o.x = 0;
969 if (r.o.y < 0)
970 pr.o.y -= r.o.y, r.o.y = 0;
971 setgattr (widget, ap);
972 gc = CreateCompatibleDC (GC);
973 SelectObject (gc, pix);
974 BitBlt (
975 gc, pr.o.x, pr.o.y, r.c.x - r.o.x + 1, r.c.y - r.o.y + 1,
976 GC, r.o.x, r.o.y, (WPU->gattr.mode == G_SRC) ? SRCCOPY : SRCINVERT
977 );
978 if (pix != bitmap->u.bmap.orig)
979 scalebitmap (widget, bitmap, scale, TRUE, -1);
980 DeleteDC (gc);
981 }
982 return 0;
983 }
984
scalebitmap(Gwidget_t * widget,Gbitmap_t * bitmap,Gsize_t scale,int copybits,int dir)985 static int scalebitmap (
986 Gwidget_t *widget, Gbitmap_t *bitmap, Gsize_t scale,
987 int copybits, int dir
988 ) {
989 Gsize_t nsize, o2n;
990 HBITMAP opix, spix;
991 COLORREF color;
992 HDC gc1, gc2;
993 int x, y, x2, y2, xp, yp;
994 double prod, rgb[3], xr2, yr2, xl2, yl2, xf2, yf2, xr, yr, xl, yl;
995
996 if (!copybits) {
997 if (dir == 1) {
998 nsize.x = (int) (bitmap->size.x * scale.x);
999 nsize.y = (int) (bitmap->size.y * scale.y);
1000 if (!(spix = CreateBitmap (
1001 (int) nsize.x, (int) nsize.y, 1, Gdepth, NULL
1002 ))) {
1003 Gerr (POS, G_ERRCANNOTCREATEBITMAP);
1004 return -1;
1005 }
1006 if (bitmap->u.bmap.scaled)
1007 DeleteObject (bitmap->u.bmap.scaled);
1008 bitmap->u.bmap.scaled = spix;
1009 bitmap->scale = scale;
1010 }
1011 return 0;
1012 }
1013 if (dir == 1) {
1014 nsize.x = (int) (bitmap->size.x * scale.x);
1015 nsize.y = (int) (bitmap->size.y * scale.y);
1016 o2n.x = 1 / scale.x, o2n.y = 1 / scale.y;
1017 if (!(spix = CreateBitmap (
1018 (int) nsize.x, (int) nsize.y, 1, Gdepth, NULL
1019 ))) {
1020 Gerr (POS, G_ERRCANNOTCREATEBITMAP);
1021 return -1;
1022 }
1023 opix = bitmap->u.bmap.orig;
1024 } else {
1025 nsize.x = (int) bitmap->size.x;
1026 nsize.y = (int) bitmap->size.y;
1027 o2n.x = scale.x, o2n.y = scale.y;
1028 spix = bitmap->u.bmap.orig;
1029 opix = bitmap->u.bmap.scaled;
1030 }
1031 gc1 = CreateCompatibleDC (GC);
1032 SelectObject (gc1, opix);
1033 gc2 = CreateCompatibleDC (GC);
1034 SelectObject (gc2, spix);
1035 prod = o2n.x * o2n.y;
1036 y = 0;
1037 yr = o2n.y;
1038 yl = 0;
1039 for (yp = 0; yp < nsize.y; yp++) {
1040 x = 0;
1041 xr = o2n.x;
1042 xl = 0;
1043 for (xp = 0; xp < nsize.x; xp++) {
1044 y2 = y;
1045 yr2 = yr;
1046 yl2 = yl;
1047 rgb[0] = rgb[1] = rgb[2] = 0;
1048 do {
1049 x2 = x;
1050 xr2 = xr;
1051 xl2 = xl;
1052 yf2 = (yl2 + yr2 > 1) ? 1 - yl2 : yr2, yr2 -= yf2;
1053 do {
1054 xf2 = (xl2 + xr2 > 1) ? 1 - xl2 : xr2, xr2 -= xf2;
1055 color = GetPixel (gc1, x2, y2);
1056 rgb[0] += (GetRValue (color) * xf2 * yf2 / prod);
1057 rgb[1] += (GetGValue (color) * xf2 * yf2 / prod);
1058 rgb[2] += (GetBValue (color) * xf2 * yf2 / prod);
1059 xl2 += xf2;
1060 if (xl2 >= 1)
1061 x2++, xl2 -= 1;
1062 } while (xr2 > 0);
1063 xr2 = o2n.x;
1064 yl2 += yf2;
1065 if (yl2 >= 1)
1066 y2++, yl2 -= 1;
1067 } while (yr2 > 0);
1068 yr2 = o2n.y;
1069 SetPixel (gc2, xp, yp, RGB (rgb[0], rgb[1], rgb[2]));
1070 x = x2;
1071 xr = xr2;
1072 xl = xl2;
1073 }
1074 y = y2;
1075 yr = yr2;
1076 yl = yl2;
1077 }
1078 DeleteDC (gc1);
1079 DeleteDC (gc2);
1080 if (dir == 1) {
1081 if (bitmap->u.bmap.scaled)
1082 DeleteObject (bitmap->u.bmap.scaled);
1083 bitmap->u.bmap.scaled = spix;
1084 bitmap->scale = scale;
1085 }
1086 return 0;
1087 }
1088
setgattr(Gwidget_t * widget,Ggattr_t * ap)1089 static void setgattr (Gwidget_t *widget, Ggattr_t *ap) {
1090 HBRUSH brush, pbrush;
1091 HPEN pen, ppen;
1092 PALETTEENTRY *colorp;
1093 long color, mode, style, width, flag, pati;
1094 double intens;
1095
1096 if (!(ap->flags & G_GATTRCOLOR))
1097 ap->color = WPU->defgattr.color;
1098 if (!(ap->flags & G_GATTRWIDTH))
1099 ap->width = WPU->defgattr.width;
1100 if (!(ap->flags & G_GATTRMODE))
1101 ap->mode = WPU->defgattr.mode;
1102 if (!(ap->flags & G_GATTRFILL))
1103 ap->fill = WPU->defgattr.fill;
1104 if (!(ap->flags & G_GATTRSTYLE))
1105 ap->style = WPU->defgattr.style;
1106 flag = FALSE;
1107 mode = ap->mode;
1108 if (mode != WPU->gattr.mode) {
1109 WPU->gattr.mode = mode;
1110 SetROP2 (GC, (int) mode);
1111 }
1112 WPU->gattr.fill = ap->fill;
1113 color = ap->color;
1114 if (color >= G_MAXCOLORS || !(WPU->colors[color].inuse))
1115 color = 1;
1116 if (color != WPU->gattr.color)
1117 WPU->gattr.color = color, flag = TRUE;
1118 width = ap->width;
1119 if (width != WPU->gattr.width)
1120 WPU->gattr.width = width, flag = TRUE;
1121 style = ap->style;
1122 if (style != WPU->gattr.style)
1123 WPU->gattr.style = style, flag = TRUE;
1124
1125 if (!flag)
1126 return;
1127 WPU->gattr.color = color;
1128 if (Gdepth == 1) {
1129 colorp = &WPU->colors[color].color;
1130 intens = (
1131 0.3 * colorp->peBlue + 0.59 * colorp->peRed +
1132 0.11 * colorp->peGreen
1133 ) / 255.0;
1134 pati = (intens <= 0.0625) ? 16 : -16.0 * (log (intens) / 2.7725887222);
1135 brush = WPU->grays[pati];
1136 } else
1137 brush = CreateSolidBrush (PALETTEINDEX (WPU->gattr.color));
1138 pbrush = SelectObject (GC, brush);
1139 if (Gdepth != 1)
1140 DeleteObject (pbrush);
1141 pen = CreatePen (
1142 (int) gstyles[WPU->gattr.style], WPU->gattr.width,
1143 PALETTEINDEX (WPU->gattr.color)
1144 );
1145 ppen = SelectObject (GC, pen);
1146 DeleteObject (ppen);
1147 SetTextColor (GC, PALETTEINDEX (WPU->gattr.color));
1148 }
1149
rdrawtopix(Gwidget_t * widget,Grect_t gr)1150 static PIXrect_t rdrawtopix (Gwidget_t *widget, Grect_t gr) {
1151 PIXrect_t pr;
1152 double tvx, tvy, twx, twy;
1153
1154 tvx = WPU->vsize.x - 1, tvy = WPU->vsize.y - 1;
1155 twx = WPU->wrect.c.x - WPU->wrect.o.x;
1156 twy = WPU->wrect.c.y - WPU->wrect.o.y;
1157 pr.o.x = tvx * (gr.o.x - WPU->wrect.o.x) / twx + 0.5;
1158 pr.o.y = tvy * (1.0 - (gr.c.y - WPU->wrect.o.y) / twy) + 0.5;
1159 pr.c.x = tvx * (gr.c.x - WPU->wrect.o.x) / twx + 0.5;
1160 pr.c.y = tvy * (1.0 - (gr.o.y - WPU->wrect.o.y) / twy) + 0.5;
1161 return pr;
1162 }
1163
pdrawtopix(Gwidget_t * widget,Gpoint_t gp)1164 static PIXpoint_t pdrawtopix (Gwidget_t *widget, Gpoint_t gp) {
1165 PIXpoint_t pp;
1166 double tvx, tvy, twx, twy;
1167
1168 tvx = WPU->vsize.x - 1, tvy = WPU->vsize.y - 1;
1169 twx = WPU->wrect.c.x - WPU->wrect.o.x;
1170 twy = WPU->wrect.c.y - WPU->wrect.o.y;
1171 pp.x = tvx * (gp.x - WPU->wrect.o.x) / twx + 0.5;
1172 pp.y = tvy * (1.0 - (gp.y - WPU->wrect.o.y) / twy) + 0.5;
1173 return pp;
1174 }
1175
sdrawtopix(Gwidget_t * widget,Gsize_t gs)1176 static PIXsize_t sdrawtopix (Gwidget_t *widget, Gsize_t gs) {
1177 PIXsize_t ps;
1178 double tvx, tvy, twx, twy;
1179
1180 tvx = WPU->vsize.x - 1, tvy = WPU->vsize.y - 1;
1181 twx = WPU->wrect.c.x - WPU->wrect.o.x;
1182 twy = WPU->wrect.c.y - WPU->wrect.o.y;
1183 ps.x = tvx * (gs.x - 1) / twx + 1.5;
1184 ps.y = tvy * (gs.y - 1) / twy + 1.5;
1185 return ps;
1186 }
1187
rdrawtobpix(Gbitmap_t * bitmap,Grect_t gr)1188 static PIXrect_t rdrawtobpix (Gbitmap_t *bitmap, Grect_t gr) {
1189 PIXrect_t pr;
1190 double tvy;
1191
1192 tvy = (int) ((bitmap->size.y - 1) * bitmap->scale.y);
1193 pr.o.x = gr.o.x + 0.5;
1194 pr.o.y = tvy - gr.c.y + 0.5;
1195 pr.c.x = gr.c.x + 0.5;
1196 pr.c.y = tvy - gr.o.y + 0.5;
1197 return pr;
1198 }
1199
pdrawtobpix(Gbitmap_t * bitmap,Gpoint_t gp)1200 static PIXpoint_t pdrawtobpix (Gbitmap_t *bitmap, Gpoint_t gp) {
1201 PIXpoint_t pp;
1202 double tvy;
1203
1204 tvy = (int) ((bitmap->size.y - 1) * bitmap->scale.y);
1205 pp.x = gp.x + 0.5;
1206 pp.y = tvy - gp.y + 0.5;
1207 return pp;
1208 }
1209