1 /********************************************************************************
2 * *
3 * D e v i c e C o n t e x t F o r W i n d o w s a n d I m a g e s *
4 * *
5 *********************************************************************************
6 * Copyright (C) 1999,2020 by Jeroen van der Zijp. All Rights Reserved. *
7 *********************************************************************************
8 * This library is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU Lesser General Public License as published by *
10 * the Free Software Foundation; either version 3 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This library is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU Lesser General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU Lesser General Public License *
19 * along with this program. If not, see <http://www.gnu.org/licenses/> *
20 ********************************************************************************/
21 #include "xincs.h"
22 #include "fxver.h"
23 #include "fxdefs.h"
24 #include "fxmath.h"
25 #include "fxkeys.h"
26 #include "FXArray.h"
27 #include "FXHash.h"
28 #include "FXMutex.h"
29 #include "FXStream.h"
30 #include "FXString.h"
31 #include "FXObject.h"
32 #include "FXSize.h"
33 #include "FXPoint.h"
34 #include "FXRectangle.h"
35 #include "FXStringDictionary.h"
36 #include "FXSettings.h"
37 #include "FXRegistry.h"
38 #include "FXAccelTable.h"
39 #include "FXVisual.h"
40 #include "FXFont.h"
41 #include "FXCursor.h"
42 #include "FXEvent.h"
43 #include "FXWindow.h"
44 #include "FXApp.h"
45 #include "FXDrawable.h"
46 #include "FXImage.h"
47 #include "FXBitmap.h"
48 #include "FXIcon.h"
49 #include "FXWindow.h"
50 #include "FXFrame.h"
51 #include "FXComposite.h"
52 #include "FXRootWindow.h"
53 #include "FXShell.h"
54 #include "FXRegion.h"
55 #include "FXDCWindow.h"
56
57
58 /*
59 Notes:
60
61 - Associate a DC with a surface before you begin using it:
62
63 long SomeWidget::onPaint(FXObject*,FXSelector,void* ptr){
64 FXDCWindow dc(this,ptr);
65 dc.drawLine(...);
66 ... jadajadajada ...
67 return 1;
68 }
69
70 The association is automatically broken when you go out of scope; the
71 destructor of the FXDCWindow does this for you.
72
73 - Optimizations: only perform style/attribute changes just before an actual
74 drawing command takes place:- X-Windows apparently already does this;
75 MS-Windows also?
76
77 - We assume the following initial state:
78
79 BLIT Function: BLT_SRC
80 Foreground: black (0)
81 Background: white (1)
82 Line Width: 0 (meaning thinnest/fastest, no guaranteed pixelation)
83 Cap Style: CAP_BUTT
84 Join Style: JOIN_MITER
85 Line Style: LINE_SOLID
86 Fill Style: FILL_SOLID
87 Fill Rule: RULE_EVEN_ODD
88 Font: None
89 Other Paremeters: To Be Determined
90
91 - Under X-Windows, end() will restore the GC to the state above; flags
92 keeps track of which changes have been made to minimize the necessary
93 updating.
94
95 - Under X, graphics_exposures should be OFF:- at least some SGI IRIX machines
96 have broken implementations of graphics_exposures.
97
98 - Try suggestions from "Kevin Radke" <kmradke@isualum.com> below:
99
100 Sorry about the huge delay with this code. Work has been horribly busy
101 and I wasn't able to dig up the CD with the original code. However, if I
102 remember
103 correctly (and this code snippet I found was from that test), I changed from
104 using
105 cosmetic pens to use geometric pens and specifying a line join style of
106 PS_JOIN_BEVEL.
107
108 I.E.
109
110 LOGBRUSH logBrush;
111 logBrush.lbStyle = BS_SOLID;
112 logBrush.lbColor = RGB(red, green, blue);
113 logBrush.lbHatch = HS_CROSS; // Not used
114
115 // NYI Only solid lines are valid on Windows 95. style is ignored
116 return ExtCreatePen (PS_GEOMETRIC | PS_JOIN_BEVEL | style,
117 width, &logBrush, 0, NULL);
118
119
120 this returns an HPEN.
121
122 I remember this being significantly slower than cosmetic pens (under NT4)
123 and at the time that I scrapped the code, and dealt with the drawing
124 differences
125 between X and Win32 at a higher level.
126
127 This won't work on Win95/Win98 (without using paths), and after a closer
128 look at
129 the docs here it makes more sense to specify PS_ENDCAP_SQUARE to draw
130 the last pixel instead of the line join style. I remember experimenting
131 with both, so
132 the code I found may have been in intermediate (unworking) version.
133
134 In any case, it isn't too hard to experiment to see which has the required
135 behavior. I've unfortunately been away from FOX work for a few months
136 or I'd try it myself.
137
138 - Device caps for DirectX:
139 http://www.molybdenium.de/devicecaps/e_index.html
140 */
141
142 using namespace FX;
143
144 namespace FX {
145
146
147 /********************************************************************************
148 * MS-Windows *
149 ********************************************************************************/
150
151 #ifdef WIN32
152
153 // This one is not defined in the Cygwin header files
154 #ifndef PS_JOIN_MASK
155 #define PS_JOIN_MASK 0x0000F000
156 #endif
157
158 // Construct for expose event painting
FXDCWindow(FXDrawable * draw,FXEvent * event)159 FXDCWindow::FXDCWindow(FXDrawable* draw,FXEvent* event):FXDC(draw->getApp()),surface(NULL),rect(0,0,0,0),devfg(0),devbg(0){
160 oldpalette=NULL;
161 oldbrush=NULL;
162 oldpen=NULL;
163 needsNewBrush=false;
164 needsNewPen=false;
165 needsPath=false;
166 needsClipReset=false;
167 begin(draw);
168 rect.x=clip.x=event->rect.x;
169 rect.y=clip.y=event->rect.y;
170 rect.w=clip.w=event->rect.w;
171 rect.h=clip.h=event->rect.h;
172 HRGN hrgn=CreateRectRgn(clip.x,clip.y,clip.x+clip.w,clip.y+clip.h);
173 SelectClipRgn((HDC)ctx,hrgn);
174 DeleteObject(hrgn);
175 }
176
177
178 // Construct for normal painting
FXDCWindow(FXDrawable * draw)179 FXDCWindow::FXDCWindow(FXDrawable* draw):FXDC(draw->getApp()),surface(NULL),rect(0,0,0,0),devfg(0),devbg(0){
180 oldpalette=NULL;
181 oldbrush=NULL;
182 oldpen=NULL;
183 needsNewBrush=false;
184 needsNewPen=false;
185 needsPath=false;
186 needsClipReset=false;
187 begin(draw);
188 }
189
190
191 // Destruct
~FXDCWindow()192 FXDCWindow::~FXDCWindow(){
193 end();
194 }
195
196
197 // Begin locks in a drawable surface
begin(FXDrawable * draw)198 void FXDCWindow::begin(FXDrawable *draw){
199 if(!draw){ fxerror("FXDCWindow::begin: NULL drawable.\n"); }
200 if(!draw->id()){ fxerror("FXDCWindow::begin: drawable not created yet.\n"); }
201
202 surface=draw; // Careful:- surface->id() can be HWND or HBITMAP depending on drawable
203 ctx=draw->GetDC();
204 rect.x=clip.x=0;
205 rect.y=clip.y=0;
206 rect.w=clip.w=draw->getWidth();
207 rect.h=clip.h=draw->getHeight();
208
209 // Select and realize palette, if necessary
210 if(surface->visual->colormap){
211 oldpalette=::SelectPalette((HDC)ctx,(HPALETTE)surface->visual->colormap,false);
212 ::RealizePalette((HDC)ctx);
213 }
214
215 devfg=~0;
216 devbg=0;
217
218 // Create our default pen (black, solid, one pixel wide)
219 LOGBRUSH lb;
220 lb.lbStyle=BS_SOLID;
221 lb.lbColor=PALETTERGB(0,0,0);
222 lb.lbHatch=0;
223 oldpen=::SelectObject((HDC)ctx,ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,1,&lb,0,NULL));
224
225 // Create our default brush (solid white, for fills)
226 lb.lbStyle=BS_SOLID;
227 lb.lbColor=PALETTERGB(255,255,255);
228 lb.lbHatch=0;
229 oldbrush=::SelectObject((HDC)ctx,CreateBrushIndirect(&lb));
230
231 // Text alignment
232 ::SetTextAlign((HDC)ctx,TA_BASELINE|TA_LEFT);
233
234 // Polygon fill mode
235 ::SetPolyFillMode((HDC)ctx,ALTERNATE);
236
237 // Reset flags
238 needsNewBrush=false;
239 needsNewPen=false;
240 needsPath=false;
241 needsClipReset=false;
242 }
243
244
245 // End unlocks the drawable surface
end()246 void FXDCWindow::end(){
247 if(ctx){
248 ::DeleteObject(::SelectObject((HDC)ctx,oldpen));
249 ::DeleteObject(::SelectObject((HDC)ctx,oldbrush));
250 if(surface->visual->colormap){
251 SelectPalette((HDC)ctx,(HPALETTE)oldpalette,false);
252 }
253 surface->ReleaseDC((HDC)ctx);
254 if(needsClipReset){
255 DWORD dwFlags=GetWindowLong((HWND)surface->id(),GWL_STYLE);
256 SetWindowLong((HWND)surface->id(),GWL_STYLE,dwFlags|WS_CLIPCHILDREN);
257 }
258 ctx=NULL;
259 }
260 surface=NULL;
261 }
262
263
264 // Read back pixel
readPixel(FXint x,FXint y)265 FXColor FXDCWindow::readPixel(FXint x,FXint y){
266 FXColor color=FXRGBA(0,0,0,0);
267 if(!surface){ fxerror("FXDCWindow::readPixel: DC not connected to drawable.\n"); }
268 if(0<=x && 0<=y && x<surface->getWidth() && y<surface->getHeight()){
269 COLORREF clr=GetPixel((HDC)ctx,x,y);
270 color=FXRGB(GetRValue(clr),GetGValue(clr),GetBValue(clr));
271 }
272 return color;
273 }
274
275
276 // Draw pixel in current foreground color
drawPoint(FXint x,FXint y)277 void FXDCWindow::drawPoint(FXint x,FXint y){
278 if(!surface){ fxerror("FXDCWindow::drawPoint: DC not connected to drawable.\n"); }
279 ::SetPixel((HDC)ctx,x,y,devfg);
280 }
281
282
283 // Draw points
drawPoints(const FXPoint * points,FXuint npoints)284 void FXDCWindow::drawPoints(const FXPoint* points,FXuint npoints){
285 FXuint i;
286 if(!surface){ fxerror("FXDCWindow::drawPoints: DC not connected to drawable.\n"); }
287 for(i=0; i<npoints; i++){
288 ::SetPixel((HDC)ctx,points[i].x,points[i].y,devfg);
289 }
290 }
291
292
293 // Draw points relative
drawPointsRel(const FXPoint * points,FXuint npoints)294 void FXDCWindow::drawPointsRel(const FXPoint* points,FXuint npoints){
295 int x=0,y=0;
296 FXuint i;
297 if(!surface){ fxerror("FXDCWindow::drawPointsRel: DC not connected to drawable.\n"); }
298 for(i=0; i<npoints; i++){
299 x+=points[i].x;
300 y+=points[i].y;
301 ::SetPixel((HDC)ctx,x,y,devfg);
302 }
303 }
304
305
306 // Draw line
drawLine(FXint x1,FXint y1,FXint x2,FXint y2)307 void FXDCWindow::drawLine(FXint x1,FXint y1,FXint x2,FXint y2){
308 if(!surface){ fxerror("FXDCWindow::drawLine: DC not connected to drawable.\n"); }
309 if(needsNewPen) updatePen();
310 if(needsPath){
311 ::BeginPath((HDC)ctx);
312 }
313 POINT pts[2];
314 pts[0].x=x1; pts[0].y=y1;
315 pts[1].x=x2; pts[1].y=y2;
316 ::Polyline((HDC)ctx,pts,2);
317 if(needsPath){
318 ::EndPath((HDC)ctx);
319 ::StrokePath((HDC)ctx);
320 }
321 }
322
323
324 // Draw lines
drawLines(const FXPoint * points,FXuint npoints)325 void FXDCWindow::drawLines(const FXPoint* points,FXuint npoints){
326 FXuint i;
327 POINT pts[1360]; // Worst case limit according to MSDN
328 if(!surface){ fxerror("FXDCWindow::drawLines: DC not connected to drawable.\n"); }
329 if(needsNewPen) updatePen();
330 if(needsPath){
331 ::BeginPath((HDC)ctx);
332 }
333 if(1360<=npoints){
334 ::MoveToEx((HDC)ctx,points[0].x,points[0].y,NULL);
335 for(i=1; i<npoints; i++) ::LineTo((HDC)ctx,points[i].x,points[i].y);
336 }
337 else{
338 for(i=0; i<npoints; i++){
339 pts[i].x=points[i].x;
340 pts[i].y=points[i].y;
341 }
342 ::Polyline((HDC)ctx,pts,npoints);
343 }
344 if(needsPath){
345 ::EndPath((HDC)ctx);
346 ::StrokePath((HDC)ctx);
347 }
348 }
349
350
351 // Draw lines relative
drawLinesRel(const FXPoint * points,FXuint npoints)352 void FXDCWindow::drawLinesRel(const FXPoint* points,FXuint npoints){
353 int x=0,y=0;
354 FXuint i;
355 POINT pts[1360]; // Worst case limit according to MSDN
356 if(!surface){ fxerror("FXDCWindow::drawLinesRel: DC not connected to drawable.\n"); }
357 if(needsNewPen) updatePen();
358 if(needsPath){
359 ::BeginPath((HDC)ctx);
360 }
361 if(1360<=npoints){
362 ::MoveToEx((HDC)ctx,points[0].x,points[0].y,NULL);
363 for(i=1; i<npoints; i++){
364 x+=points[i].x;
365 y+=points[i].y;
366 ::LineTo((HDC)ctx,x,y);
367 }
368 }
369 else{
370 for(i=0; i<npoints; i++){
371 x+=points[i].x; pts[i].x=x;
372 y+=points[i].y; pts[i].y=y;
373 }
374 ::Polyline((HDC)ctx,pts,npoints);
375 }
376 if(needsPath){
377 ::EndPath((HDC)ctx);
378 ::StrokePath((HDC)ctx);
379 }
380 }
381
382
383 // Draw line segments
drawLineSegments(const FXSegment * segments,FXuint nsegments)384 void FXDCWindow::drawLineSegments(const FXSegment* segments,FXuint nsegments){
385 FXuint i;
386 POINT pts[2];
387 if(!surface){ fxerror("FXDCWindow::drawLineSegments: DC not connected to drawable.\n"); }
388 if(needsNewPen) updatePen();
389 if(needsPath){
390 ::BeginPath((HDC)ctx);
391 }
392 for(i=0; i<nsegments; i++){
393 pts[0].x=segments[i].x1; pts[0].y=segments[i].y1;
394 pts[1].x=segments[i].x2; pts[1].y=segments[i].y2;
395 ::Polyline((HDC)ctx,pts,2);
396 }
397 if(needsPath){
398 ::EndPath((HDC)ctx);
399 ::StrokePath((HDC)ctx);
400 }
401 }
402
403
404 // Unfilled rectangle
drawRectangle(FXint x,FXint y,FXint w,FXint h)405 void FXDCWindow::drawRectangle(FXint x,FXint y,FXint w,FXint h){
406 if(!surface){ fxerror("FXDCWindow::drawRectangle: DC not connected to drawable.\n"); }
407 if(needsNewPen) updatePen();
408 HBRUSH hbrush=(HBRUSH)::SelectObject((HDC)ctx,(HBRUSH)GetStockObject(NULL_BRUSH));
409 ::Rectangle((HDC)ctx,x,y,x+w+1,y+h+1);
410 ::SelectObject((HDC)ctx,hbrush);
411 }
412
413
414 // Draw unfilled rectangles
drawRectangles(const FXRectangle * rectangles,FXuint nrectangles)415 void FXDCWindow::drawRectangles(const FXRectangle* rectangles,FXuint nrectangles){
416 FXuint i;
417 if(!surface){ fxerror("FXDCWindow::drawRectangles: DC not connected to drawable.\n"); }
418 if(needsNewPen) updatePen();
419 HBRUSH hbrush=(HBRUSH)::SelectObject((HDC)ctx,(HBRUSH)GetStockObject(NULL_BRUSH));
420 for(i=0; i<nrectangles; i++){
421 ::Rectangle((HDC)ctx,rectangles[i].x,rectangles[i].y,rectangles[i].x+rectangles[i].w+1,rectangles[i].y+rectangles[i].h+1);
422 }
423 ::SelectObject((HDC)ctx,hbrush);
424 }
425
426
427 // Unfilled rounded rectangle
drawRoundRectangle(FXint x,FXint y,FXint w,FXint h,FXint ew,FXint eh)428 void FXDCWindow::drawRoundRectangle(FXint x,FXint y,FXint w,FXint h,FXint ew,FXint eh){
429 if(!surface){ fxerror("FXDCWindow::drawRoundRectangle: DC not connected to drawable.\n"); }
430 if(needsNewPen) updatePen();
431 HBRUSH hbrush=(HBRUSH)::SelectObject((HDC)ctx,(HBRUSH)GetStockObject(NULL_BRUSH));
432 if(ew+ew>w) ew=w>>1;
433 if(eh+eh>h) eh=h>>1;
434 ::RoundRect((HDC)ctx,x,y,x+w+1,y+h+1,ew,eh);
435 ::SelectObject((HDC)ctx,hbrush);
436 }
437
438
439 // Draw arc; angles in degrees*64, ang2 relative to ang1
440 // If angle is negative flip the start and end; also, if ang2 is zero,
441 // don't draw anything at all (patch: Sander Jansen <sander@knology.net>).
drawArc(FXint x,FXint y,FXint w,FXint h,FXint ang1,FXint ang2)442 void FXDCWindow::drawArc(FXint x,FXint y,FXint w,FXint h,FXint ang1,FXint ang2){
443 FXbool reversed=(ang2<0);
444 if(!surface){ fxerror("FXDCWindow::drawArc: DC not connected to drawable.\n"); }
445 if(ang2==0) return;
446 if(needsNewPen) updatePen();
447 ang2+=ang1;
448 w+=1;
449 h+=1;
450 int xStart=int(x+0.5*w+w*Math::cos(ang1*PI/(180.0*64.0)));
451 int yStart=int(y+0.5*h-h*Math::sin(ang1*PI/(180.0*64.0)));
452 int xEnd=int(x+0.5*w+w*Math::cos(ang2*PI/(180.0*64.0)));
453 int yEnd=int(y+0.5*h-h*Math::sin(ang2*PI/(180.0*64.0)));
454 if(needsPath){
455 ::BeginPath((HDC)ctx);
456 }
457 if(reversed)
458 ::Arc((HDC)ctx,x,y,x+w,y+h,xEnd,yEnd,xStart,yStart);
459 else
460 ::Arc((HDC)ctx,x,y,x+w,y+h,xStart,yStart,xEnd,yEnd);
461 if(needsPath){
462 ::EndPath((HDC)ctx);
463 ::StrokePath((HDC)ctx);
464 }
465 }
466
467
468 // Draw arcs
drawArcs(const FXArc * arcs,FXuint narcs)469 void FXDCWindow::drawArcs(const FXArc* arcs,FXuint narcs){
470 FXuint i;
471 if(!surface){ fxerror("FXDCWindow::drawArcs: DC not connected to drawable.\n"); }
472 for(i=0; i<narcs; i++){
473 drawArc(arcs[i].x,arcs[i].y,arcs[i].w,arcs[i].h,arcs[i].a,arcs[i].b);
474 }
475 }
476
477
478 // Draw ellipse
drawEllipse(FXint x,FXint y,FXint w,FXint h)479 void FXDCWindow::drawEllipse(FXint x,FXint y,FXint w,FXint h){
480 if(!surface){ fxerror("FXDCWindow::drawEllipse: DC not connected to drawable.\n"); }
481 if(needsNewBrush) updateBrush();
482 if(needsNewPen) updatePen();
483 w+=1;
484 h+=1;
485 if(needsPath){
486 ::BeginPath((HDC)ctx);
487 }
488 ::Arc((HDC)ctx,x,y,x+w,y+h,x+(w>>1),y+(h>>1),x+(w>>1),y+(h>>1));
489 if(needsPath){
490 ::EndPath((HDC)ctx);
491 ::StrokePath((HDC)ctx);
492 }
493 }
494
495
496 // Fill using currently selected ROP code
fillRectangle(FXint x,FXint y,FXint w,FXint h)497 void FXDCWindow::fillRectangle(FXint x,FXint y,FXint w,FXint h){
498 if(!surface){ fxerror("FXDCWindow::fillRectangle: DC not connected to drawable.\n"); }
499 if(needsNewBrush) updateBrush();
500 HPEN hpen=(HPEN)::SelectObject((HDC)ctx,GetStockObject(NULL_PEN));
501 ::Rectangle((HDC)ctx,x,y,x+w+1,y+h+1);
502 ::SelectObject((HDC)ctx,hpen);
503 }
504
505
506 // Fill using currently selected ROP code
fillRectangles(const FXRectangle * rectangles,FXuint nrectangles)507 void FXDCWindow::fillRectangles(const FXRectangle* rectangles,FXuint nrectangles){
508 FXuint i;
509 if(!surface){ fxerror("FXDCWindow::fillRectangles: DC not connected to drawable.\n"); }
510 if(needsNewBrush) updateBrush();
511 HPEN hpen=(HPEN)::SelectObject((HDC)ctx,GetStockObject(NULL_PEN));
512 for(i=0; i<nrectangles; i++){
513 ::Rectangle((HDC)ctx,rectangles[i].x,rectangles[i].y,rectangles[i].x+rectangles[i].w+1,rectangles[i].y+rectangles[i].h+1);
514 }
515 ::SelectObject((HDC)ctx,hpen);
516 }
517
518
519 // Fill using currently selected ROP mode
fillRoundRectangle(FXint x,FXint y,FXint w,FXint h,FXint ew,FXint eh)520 void FXDCWindow::fillRoundRectangle(FXint x,FXint y,FXint w,FXint h,FXint ew,FXint eh){
521 if(!surface){ fxerror("FXDCWindow::fillRoundRectangle: DC not connected to drawable.\n"); }
522 if(needsNewBrush) updateBrush();
523 HPEN hpen=(HPEN)::SelectObject((HDC)ctx,GetStockObject(NULL_PEN));
524 if(ew+ew>w) ew=w>>1;
525 if(eh+eh>h) eh=h>>1;
526 ::RoundRect((HDC)ctx,x,y,x+w+1,y+h+1,ew,eh);
527 ::SelectObject((HDC)ctx,hpen);
528 }
529
530
531 // Fill chord
fillChord(FXint x,FXint y,FXint w,FXint h,FXint ang1,FXint ang2)532 void FXDCWindow::fillChord(FXint x,FXint y,FXint w,FXint h,FXint ang1,FXint ang2){
533 FXbool reversed=(ang2<0);
534 if(!surface){ fxerror("FXDCWindow::fillChord: DC not connected to drawable.\n"); }
535 if(ang2==0) return;
536 if(needsNewBrush) updateBrush();
537 ang2+=ang1;
538 w+=1;
539 h+=1;
540 int xStart=int(x+0.5*w+w*Math::cos(ang1*PI/(180.0*64.0)));
541 int yStart=int(y+0.5*h-h*Math::sin(ang1*PI/(180.0*64.0)));
542 int xEnd=int(x+0.5*w+w*Math::cos(ang2*PI/(180.0*64.0)));
543 int yEnd=int(y+0.5*h-h*Math::sin(ang2*PI/(180.0*64.0)));
544 HPEN hpen=(HPEN)::SelectObject((HDC)ctx,GetStockObject(NULL_PEN));
545 if(reversed)
546 ::Chord((HDC)ctx,x,y,x+w,y+h,xEnd,yEnd,xStart,yStart);
547 else
548 ::Chord((HDC)ctx,x,y,x+w,y+h,xStart,yStart,xEnd,yEnd);
549 ::SelectObject((HDC)ctx,hpen);
550 }
551
552
553 // Fill chords
fillChords(const FXArc * chords,FXuint nchords)554 void FXDCWindow::fillChords(const FXArc* chords,FXuint nchords){
555 FXuint i;
556 if(!surface){ fxerror("FXDCWindow::fillChords: DC not connected to drawable.\n"); }
557 for(i=0; i<nchords; i++){
558 fillChord(chords[i].x,chords[i].y,chords[i].w,chords[i].h,chords[i].a,chords[i].b);
559 }
560 }
561
562
563 // Draw filled arc; angles are in degrees*64; ang2 is relative from ang1
564 // If angle is negative flip the start and end; also, if ang2 is zero,
565 // don't draw anything at all (patch: Sander Jansen <sander@knology.net>).
fillArc(FXint x,FXint y,FXint w,FXint h,FXint ang1,FXint ang2)566 void FXDCWindow::fillArc(FXint x,FXint y,FXint w,FXint h,FXint ang1,FXint ang2){
567 FXbool reversed=(ang2<0);
568 if(!surface){ fxerror("FXDCWindow::fillArc: DC not connected to drawable.\n"); }
569 if(ang2==0) return;
570 if(needsNewBrush) updateBrush();
571 ang2+=ang1;
572 w+=1;
573 h+=1;
574 int xStart=int(x+0.5*w+w*Math::cos(ang1*PI/(180.0*64.0)));
575 int yStart=int(y+0.5*h-h*Math::sin(ang1*PI/(180.0*64.0)));
576 int xEnd=int(x+0.5*w+w*Math::cos(ang2*PI/(180.0*64.0)));
577 int yEnd=int(y+0.5*h-h*Math::sin(ang2*PI/(180.0*64.0)));
578 HPEN hpen=(HPEN)::SelectObject((HDC)ctx,GetStockObject(NULL_PEN));
579 if(reversed)
580 ::Pie((HDC)ctx,x,y,x+w,y+h,xEnd,yEnd,xStart,yStart);
581 else
582 ::Pie((HDC)ctx,x,y,x+w,y+h,xStart,yStart,xEnd,yEnd);
583 ::SelectObject((HDC)ctx,hpen);
584 }
585
586 //Ellipse((HDC)ctx,x,y,x+w,y+h);
587
588 // Fill arcs
fillArcs(const FXArc * arcs,FXuint narcs)589 void FXDCWindow::fillArcs(const FXArc* arcs,FXuint narcs){
590 FXuint i;
591 if(!surface){ fxerror("FXDCWindow::fillArcs: DC not connected to drawable.\n"); }
592 for(i=0; i<narcs; i++){
593 fillArc(arcs[i].x,arcs[i].y,arcs[i].w,arcs[i].h,arcs[i].a,arcs[i].b);
594 }
595 }
596
597
598 // Fill ellipse
fillEllipse(FXint x,FXint y,FXint w,FXint h)599 void FXDCWindow::fillEllipse(FXint x,FXint y,FXint w,FXint h){
600 if(!surface){ fxerror("FXDCWindow::fillEllipse: DC not connected to drawable.\n"); }
601 if(needsNewBrush) updateBrush();
602 w+=1;
603 h+=1;
604 HPEN hpen=(HPEN)::SelectObject((HDC)ctx,GetStockObject(NULL_PEN));
605 ::Pie((HDC)ctx,x,y,x+w,y+h,x+(w>>1),y+(h>>1),x+(w>>1),y+(h>>1));
606 ::SelectObject((HDC)ctx,hpen);
607 }
608
609
610 // Filled simple polygon
fillPolygon(const FXPoint * points,FXuint npoints)611 void FXDCWindow::fillPolygon(const FXPoint* points,FXuint npoints){
612 FXuint i;
613 POINT pts[1360]; // Worst case limit according to MSDN
614 if(!surface){ fxerror("FXDCWindow::fillPolygon: DC not connected to drawable.\n"); }
615 if(npoints>=1360){ fxerror("FXDCWindow::fillPolygon: too many points.\n"); }
616 if(needsNewBrush) updateBrush();
617 HPEN hpen=(HPEN)::SelectObject((HDC)ctx,GetStockObject(NULL_PEN));
618 for(i=0; i<npoints; i++){
619 pts[i].x=points[i].x;
620 pts[i].y=points[i].y;
621 }
622 ::Polygon((HDC)ctx,pts,npoints);
623 ::SelectObject((HDC)ctx,hpen);
624 }
625
626
627 // Filled concave polygon
fillConcavePolygon(const FXPoint * points,FXuint npoints)628 void FXDCWindow::fillConcavePolygon(const FXPoint* points,FXuint npoints){
629 FXuint i;
630 POINT pts[1360]; // Worst case limit according to MSDN
631 if(!surface){ fxerror("FXDCWindow::fillConcavePolygon: DC not connected to drawable.\n"); }
632 if(npoints>=1360){ fxerror("FXDCWindow::fillConcavePolygon: too many points.\n"); }
633 if(needsNewBrush) updateBrush();
634 HPEN hpen=(HPEN)::SelectObject((HDC)ctx,GetStockObject(NULL_PEN));
635 for(i=0; i<npoints; i++){
636 pts[i].x=points[i].x;
637 pts[i].y=points[i].y;
638 }
639 ::Polygon((HDC)ctx,pts,npoints);
640 ::SelectObject((HDC)ctx,hpen);
641 }
642
643
644 // Filled complex polygon relative
fillComplexPolygon(const FXPoint * points,FXuint npoints)645 void FXDCWindow::fillComplexPolygon(const FXPoint* points,FXuint npoints){
646 FXuint i;
647 POINT pts[1360]; // Worst case limit according to MSDN
648 if(!surface){ fxerror("FXDCWindow::fillComplexPolygon: DC not connected to drawable.\n"); }
649 if(npoints>=1360){ fxerror("FXDCWindow::fillComplexPolygon: too many points.\n"); }
650 if(needsNewBrush) updateBrush();
651 HPEN hpen=(HPEN)::SelectObject((HDC)ctx,GetStockObject(NULL_PEN));
652 for(i=0; i<npoints; i++){
653 pts[i].x=points[i].x;
654 pts[i].y=points[i].y;
655 }
656 ::Polygon((HDC)ctx,pts,npoints);
657 ::SelectObject((HDC)ctx,hpen);
658 }
659
660
661 // Filled simple polygon with relative points
fillPolygonRel(const FXPoint * points,FXuint npoints)662 void FXDCWindow::fillPolygonRel(const FXPoint* points,FXuint npoints){
663 int x=0,y=0;
664 FXuint i;
665 POINT pts[1360]; // Worst case limit according to MSDN
666 if(!surface){ fxerror("FXDCWindow::fillPolygonRel: DC not connected to drawable.\n"); }
667 if(npoints>=1360){ fxerror("FXDCWindow::fillPolygonRel: too many points.\n"); }
668 if(needsNewBrush) updateBrush();
669 HPEN hpen=(HPEN)::SelectObject((HDC)ctx,GetStockObject(NULL_PEN));
670 for(i=0; i<npoints; i++){
671 x+=points[i].x; pts[i].x=x;
672 y+=points[i].y; pts[i].y=y;
673 }
674 ::Polygon((HDC)ctx,pts,npoints);
675 ::SelectObject((HDC)ctx,hpen);
676 }
677
678
679 // Filled concave polygon relative
fillConcavePolygonRel(const FXPoint * points,FXuint npoints)680 void FXDCWindow::fillConcavePolygonRel(const FXPoint* points,FXuint npoints){
681 int x=0,y=0;
682 FXuint i;
683 POINT pts[1360]; // Worst case limit according to MSDN
684 if(!surface){ fxerror("FXDCWindow::fillConcavePolygonRel: DC not connected to drawable.\n"); }
685 if(npoints>=1360){ fxerror("FXDCWindow::fillConcavePolygonRel: too many points.\n"); }
686 if(needsNewBrush) updateBrush();
687 HPEN hpen=(HPEN)::SelectObject((HDC)ctx,GetStockObject(NULL_PEN));
688 for(i=0; i<npoints; i++){
689 x+=points[i].x; pts[i].x=x;
690 y+=points[i].y; pts[i].y=y;
691 }
692 ::Polygon((HDC)ctx,pts,npoints);
693 ::SelectObject((HDC)ctx,hpen);
694 }
695
696
697 // Filled complex polygon relative
fillComplexPolygonRel(const FXPoint * points,FXuint npoints)698 void FXDCWindow::fillComplexPolygonRel(const FXPoint* points,FXuint npoints){
699 int x=0,y=0;
700 FXuint i;
701 POINT pts[1360]; // Worst case limit according to MSDN
702 if(!surface){ fxerror("FXDCWindow::fillComplexPolygonRel: DC not connected to drawable.\n"); }
703 if(npoints>=1360){ fxerror("FXDCWindow::fillComplexPolygonRel: too many points.\n"); }
704 if(needsNewBrush) updateBrush();
705 HPEN hpen=(HPEN)::SelectObject((HDC)ctx,GetStockObject(NULL_PEN));
706 for(i=0; i<npoints; i++){
707 x+=points[i].x; pts[i].x=x;
708 y+=points[i].y; pts[i].y=y;
709 }
710 ::Polygon((HDC)ctx,pts,npoints);
711 ::SelectObject((HDC)ctx,hpen);
712 }
713
714
715 // Fill vertical gradient rectangle
fillVerticalGradient(FXint x,FXint y,FXint w,FXint h,FXColor top,FXColor bottom)716 void FXDCWindow::fillVerticalGradient(FXint x,FXint y,FXint w,FXint h,FXColor top,FXColor bottom){
717 #if defined(__BORLANDC__) || defined(__WATCOMC__) || defined(__CYGWIN__) || (_MSC_VER >= 1300)
718 TRIVERTEX v[2];
719 GRADIENT_RECT r;
720 r.UpperLeft=0;
721 r.LowerRight=1;
722 v[0].x=x;
723 v[0].y=y;
724 v[0].Red=FXREDVAL(top)<<8;
725 v[0].Green=FXGREENVAL(top)<<8;
726 v[0].Blue=FXBLUEVAL(top)<<8;
727 v[0].Alpha=0xFF00;
728 v[1].x=x+w;
729 v[1].y=y+h;
730 v[1].Red=FXREDVAL(bottom)<<8;
731 v[1].Green=FXGREENVAL(bottom)<<8;
732 v[1].Blue=FXBLUEVAL(bottom)<<8;
733 v[1].Alpha=0xFF00;
734 ::GradientFill((HDC)ctx,v,2,&r,1,GRADIENT_FILL_RECT_V);
735 #endif
736 }
737
738
739 // Fill horizontal gradient rectangle
fillHorizontalGradient(FXint x,FXint y,FXint w,FXint h,FXColor left,FXColor right)740 void FXDCWindow::fillHorizontalGradient(FXint x,FXint y,FXint w,FXint h,FXColor left,FXColor right){
741 #if defined(__BORLANDC__) || defined(__WATCOMC__) || defined(__CYGWIN__) || (_MSC_VER >= 1300)
742 TRIVERTEX v[2];
743 GRADIENT_RECT r;
744 r.UpperLeft=0;
745 r.LowerRight=1;
746 v[0].x=x;
747 v[0].y=y;
748 v[0].Red=FXREDVAL(left)<<8;
749 v[0].Green=FXGREENVAL(left)<<8;
750 v[0].Blue=FXBLUEVAL(left)<<8;
751 v[0].Alpha=0xFF00;
752 v[1].x=x+w;
753 v[1].y=y+h;
754 v[1].Red=FXREDVAL(right)<<8;
755 v[1].Green=FXGREENVAL(right)<<8;
756 v[1].Blue=FXBLUEVAL(right)<<8;
757 v[1].Alpha=0xFF00;
758 ::GradientFill((HDC)ctx,v,2,&r,1,GRADIENT_FILL_RECT_H);
759 #endif
760 }
761
762
763 // Set text font
setFont(FXFont * fnt)764 void FXDCWindow::setFont(FXFont *fnt){
765 if(!surface){ fxerror("FXDCWindow::setFont: DC not connected to drawable.\n"); }
766 if(!fnt || !fnt->id()){ fxerror("FXDCWindow::setFont: illegal or NULL font specified.\n"); }
767 ::SelectObject((HDC)ctx,fnt->id());
768 font=fnt;
769 }
770
771
772 // Draw string with base line starting at x, y
drawText(FXint x,FXint y,const FXchar * string,FXuint length)773 void FXDCWindow::drawText(FXint x,FXint y,const FXchar* string,FXuint length){
774 if(!surface){ fxerror("FXDCWindow::drawText: DC not connected to drawable.\n"); }
775 if(!font){ fxerror("FXDCWindow::drawText: no font selected.\n"); }
776 FXnchar sbuffer[4096];
777 FXint count=utf2ncs(sbuffer,string,ARRAYNUMBER(sbuffer),length);
778 FXint bkmode=::SetBkMode((HDC)ctx,TRANSPARENT);
779 ::TextOutW((HDC)ctx,x,y,sbuffer,count);
780 ::SetBkMode((HDC)ctx,bkmode);
781 }
782
783
784 // Draw text starting at x, y over filled background
drawImageText(FXint x,FXint y,const FXchar * string,FXuint length)785 void FXDCWindow::drawImageText(FXint x,FXint y,const FXchar* string,FXuint length){
786 if(!surface){ fxerror("FXDCWindow::drawImageText: DC not connected to drawable.\n"); }
787 if(!font){ fxerror("FXDCWindow::drawImageText: no font selected.\n"); }
788 FXnchar sbuffer[4096];
789 FXint count=utf2ncs(sbuffer,string,ARRAYNUMBER(sbuffer),length);
790 FXint bkmode=::SetBkMode((HDC)ctx,OPAQUE);
791 ::TextOutW((HDC)ctx,x,y,sbuffer,count);
792 // RECT r;
793 // r.left=clip.x; r.top=clip.y; r.right=clip.x+clip.w; r.bottom=clip.y+clip.h;
794 // ExtTextOutW((HDC)ctx,x,y,ETO_OPAQUE|ETO_CLIPPED,&r,sbuffer,count,NULL);
795 ::SetBkMode((HDC)ctx,bkmode);
796 }
797
798
799 // Draw string with base line starting at x, y
drawText(FXint x,FXint y,const FXString & string)800 void FXDCWindow::drawText(FXint x,FXint y,const FXString& string){
801 drawText(x,y,string.text(),string.length());
802 }
803
804
805 // Draw text starting at x, y over filled background
drawImageText(FXint x,FXint y,const FXString & string)806 void FXDCWindow::drawImageText(FXint x,FXint y,const FXString& string){
807 drawImageText(x,y,string.text(),string.length());
808 }
809
810
811 // Draw area from source
812 // Some of these ROP codes do not have names; the full list can be found in the MSDN docs
813 // at Platform SDK/Reference/Appendixes/Win32 Appendixes/Raster Operation Codes/Ternary Raster Operations
drawArea(const FXDrawable * source,FXint sx,FXint sy,FXint sw,FXint sh,FXint dx,FXint dy)814 void FXDCWindow::drawArea(const FXDrawable* source,FXint sx,FXint sy,FXint sw,FXint sh,FXint dx,FXint dy){
815 if(!surface){ fxerror("FXDCWindow::drawArea: DC not connected to drawable.\n"); }
816 if(!source || !source->id()){ fxerror("FXDCWindow::drawArea: illegal source specified.\n"); }
817 HDC shdc=(HDC)source->GetDC();
818 switch(rop){
819 case BLT_CLR: // D := 0
820 ::BitBlt((HDC)ctx,dx,dy,sw,sh,shdc,sx,sy,BLACKNESS);
821 break;
822 case BLT_SRC_AND_DST: // D := S & D
823 ::BitBlt((HDC)ctx,dx,dy,sw,sh,shdc,sx,sy,SRCAND);
824 break;
825 case BLT_SRC_AND_NOT_DST: // D := S & ~D
826 ::BitBlt((HDC)ctx,dx,dy,sw,sh,shdc,sx,sy,SRCERASE);
827 break;
828 case BLT_SRC: // D := S
829 ::BitBlt((HDC)ctx,dx,dy,sw,sh,shdc,sx,sy,SRCCOPY);
830 break;
831 case BLT_NOT_SRC_AND_DST: // D := ~S & D
832 ::BitBlt((HDC)ctx,dx,dy,sw,sh,shdc,sx,sy,0x220326);
833 break;
834 case BLT_DST: // D := D
835 break;
836 case BLT_SRC_XOR_DST: // D := S ^ D
837 ::BitBlt((HDC)ctx,dx,dy,sw,sh,shdc,sx,sy,SRCINVERT);
838 break;
839 case BLT_SRC_OR_DST: // D := S | D
840 ::BitBlt((HDC)ctx,dx,dy,sw,sh,shdc,sx,sy,SRCPAINT);
841 break;
842 case BLT_NOT_SRC_AND_NOT_DST: // D := ~S & ~D == D := ~(S | D)
843 ::BitBlt((HDC)ctx,dx,dy,sw,sh,shdc,sx,sy,NOTSRCERASE);
844 break;
845 case BLT_NOT_SRC_XOR_DST: // D := ~S ^ D
846 ::BitBlt((HDC)ctx,dx,dy,sw,sh,shdc,sx,sy,0x990066); // Not sure about this one
847 break;
848 case BLT_NOT_DST: // D := ~D
849 ::BitBlt((HDC)ctx,dx,dy,sw,sh,shdc,sx,sy,DSTINVERT);
850 break;
851 case BLT_SRC_OR_NOT_DST: // D := S | ~D
852 ::BitBlt((HDC)ctx,dx,dy,sw,sh,shdc,sx,sy,0xDD0228);
853 break;
854 case BLT_NOT_SRC: // D := ~S
855 ::BitBlt((HDC)ctx,dx,dy,sw,sh,shdc,sx,sy,NOTSRCCOPY);
856 break;
857 case BLT_NOT_SRC_OR_DST: // D := ~S | D
858 ::BitBlt((HDC)ctx,dx,dy,sw,sh,shdc,sx,sy,MERGEPAINT);
859 break;
860 case BLT_NOT_SRC_OR_NOT_DST: // D := ~S | ~D == ~(S & D)
861 ::BitBlt((HDC)ctx,dx,dy,sw,sh,shdc,sx,sy,0x7700E6);
862 break;
863 case BLT_SET: // D := 1
864 ::BitBlt((HDC)ctx,dx,dy,sw,sh,shdc,sx,sy,WHITENESS);
865 break;
866 }
867 source->ReleaseDC(shdc);
868 }
869
870
871 // Draw area stretched area from source
drawArea(const FXDrawable * source,FXint sx,FXint sy,FXint sw,FXint sh,FXint dx,FXint dy,FXint dw,FXint dh)872 void FXDCWindow::drawArea(const FXDrawable* source,FXint sx,FXint sy,FXint sw,FXint sh,FXint dx,FXint dy,FXint dw,FXint dh){
873 if(!surface){ fxerror("FXDCWindow::drawArea: DC not connected to drawable.\n"); }
874 if(!source || !source->id()){ fxerror("FXDCWindow::drawArea: illegal source specified.\n"); }
875 HDC shdc=(HDC)source->GetDC();
876 switch(rop){
877 case BLT_CLR: // D := 0
878 ::StretchBlt((HDC)ctx,dx,dy,dw,dh,shdc,sx,sy,sw,sh,BLACKNESS);
879 break;
880 case BLT_SRC_AND_DST: // D := S & D
881 ::StretchBlt((HDC)ctx,dx,dy,dw,dh,shdc,sx,sy,sw,sh,SRCAND);
882 break;
883 case BLT_SRC_AND_NOT_DST: // D := S & ~D
884 ::StretchBlt((HDC)ctx,dx,dy,dw,dh,shdc,sx,sy,sw,sh,SRCERASE);
885 break;
886 case BLT_SRC: // D := S
887 ::StretchBlt((HDC)ctx,dx,dy,dw,dh,shdc,sx,sy,sw,sh,SRCCOPY);
888 break;
889 case BLT_NOT_SRC_AND_DST: // D := ~S & D
890 ::StretchBlt((HDC)ctx,dx,dy,dw,dh,shdc,sx,sy,sw,sh,0x220326);
891 break;
892 case BLT_DST: // D := D
893 break;
894 case BLT_SRC_XOR_DST: // D := S ^ D
895 ::StretchBlt((HDC)ctx,dx,dy,dw,dh,shdc,sx,sy,sw,sh,SRCINVERT);
896 break;
897 case BLT_SRC_OR_DST: // D := S | D
898 ::StretchBlt((HDC)ctx,dx,dy,dw,dh,shdc,sx,sy,sw,sh,SRCPAINT);
899 break;
900 case BLT_NOT_SRC_AND_NOT_DST: // D := ~S & ~D == D := ~(S | D)
901 ::StretchBlt((HDC)ctx,dx,dy,dw,dh,shdc,sx,sy,sw,sh,NOTSRCERASE);
902 break;
903 case BLT_NOT_SRC_XOR_DST: // D := ~S ^ D
904 ::StretchBlt((HDC)ctx,dx,dy,dw,dh,shdc,sx,sy,sw,sh,0x990066); // Not sure about this one
905 break;
906 case BLT_NOT_DST: // D := ~D
907 ::StretchBlt((HDC)ctx,dx,dy,dw,dh,shdc,sx,sy,sw,sh,DSTINVERT);
908 break;
909 case BLT_SRC_OR_NOT_DST: // D := S | ~D
910 ::StretchBlt((HDC)ctx,dx,dy,dw,dh,shdc,sx,sy,sw,sh,0xDD0228);
911 break;
912 case BLT_NOT_SRC: // D := ~S
913 ::StretchBlt((HDC)ctx,dx,dy,dw,dh,shdc,sx,sy,sw,sh,NOTSRCCOPY);
914 break;
915 case BLT_NOT_SRC_OR_DST: // D := ~S | D
916 ::StretchBlt((HDC)ctx,dx,dy,dw,dh,shdc,sx,sy,sw,sh,MERGEPAINT);
917 break;
918 case BLT_NOT_SRC_OR_NOT_DST: // D := ~S | ~D == ~(S & D)
919 ::StretchBlt((HDC)ctx,dx,dy,dw,dh,shdc,sx,sy,sw,sh,0x7700E6);
920 break;
921 case BLT_SET: // D := 1
922 ::StretchBlt((HDC)ctx,dx,dy,dw,dh,shdc,sx,sy,sw,sh,WHITENESS);
923 break;
924 }
925 source->ReleaseDC(shdc);
926 }
927
928
929 // Draw image
drawImage(const FXImage * image,FXint dx,FXint dy)930 void FXDCWindow::drawImage(const FXImage* image,FXint dx,FXint dy){
931 if(!surface){ fxerror("FXDCWindow::drawImage: DC not connected to drawable.\n"); }
932 if(!image || !image->id()){ fxerror("FXDCWindow::drawImage: illegal image specified.\n"); }
933 HDC dcMem=(HDC)image->GetDC();
934 switch(rop){
935 case BLT_CLR: // D := 0
936 ::BitBlt((HDC)ctx,dx,dy,image->width,image->height,dcMem,0,0,BLACKNESS);
937 break;
938 case BLT_SRC_AND_DST: // D := S & D
939 ::BitBlt((HDC)ctx,dx,dy,image->width,image->height,dcMem,0,0,SRCAND);
940 break;
941 case BLT_SRC_AND_NOT_DST: // D := S & ~D
942 ::BitBlt((HDC)ctx,dx,dy,image->width,image->height,dcMem,0,0,SRCERASE);
943 break;
944 case BLT_SRC: // D := S
945 ::BitBlt((HDC)ctx,dx,dy,image->width,image->height,dcMem,0,0,SRCCOPY);
946 break;
947 case BLT_NOT_SRC_AND_DST: // D := ~S & D
948 ::BitBlt((HDC)ctx,dx,dy,image->width,image->height,dcMem,0,0,0x220326);
949 break;
950 case BLT_DST: // D := D
951 break;
952 case BLT_SRC_XOR_DST: // D := S ^ D
953 ::BitBlt((HDC)ctx,dx,dy,image->width,image->height,dcMem,0,0,SRCINVERT);
954 break;
955 case BLT_SRC_OR_DST: // D := S | D
956 ::BitBlt((HDC)ctx,dx,dy,image->width,image->height,dcMem,0,0,SRCPAINT);
957 break;
958 case BLT_NOT_SRC_AND_NOT_DST: // D := ~S & ~D == D := ~(S | D)
959 ::BitBlt((HDC)ctx,dx,dy,image->width,image->height,dcMem,0,0,NOTSRCERASE);
960 break;
961 case BLT_NOT_SRC_XOR_DST: // D := ~S ^ D
962 ::BitBlt((HDC)ctx,dx,dy,image->width,image->height,dcMem,0,0,0x990066); // Not sure about this one
963 break;
964 case BLT_NOT_DST: // D := ~D
965 ::BitBlt((HDC)ctx,dx,dy,image->width,image->height,dcMem,0,0,DSTINVERT);
966 break;
967 case BLT_SRC_OR_NOT_DST: // D := S | ~D
968 ::BitBlt((HDC)ctx,dx,dy,image->width,image->height,dcMem,0,0,0xDD0228);
969 break;
970 case BLT_NOT_SRC: // D := ~S
971 ::BitBlt((HDC)ctx,dx,dy,image->width,image->height,dcMem,0,0,NOTSRCCOPY);
972 break;
973 case BLT_NOT_SRC_OR_DST: // D := ~S | D
974 ::BitBlt((HDC)ctx,dx,dy,image->width,image->height,dcMem,0,0,MERGEPAINT);
975 break;
976 case BLT_NOT_SRC_OR_NOT_DST: // D := ~S | ~D == ~(S & D)
977 ::BitBlt((HDC)ctx,dx,dy,image->width,image->height,dcMem,0,0,0x7700E6);
978 break;
979 case BLT_SET: // D := 1
980 ::BitBlt((HDC)ctx,dx,dy,image->width,image->height,dcMem,0,0,WHITENESS);
981 break;
982 /*
983 BLENDFUNCTION bf;
984 bf.BlendOp=AC_SRC_OVER; // For RGBA image
985 bf.BlendFlags=0;
986 bf.SourceConstantAlpha=0xff;
987 bf.AlphaFormat=AC_SRC_ALPHA;
988 AlphaBlend((HDC)ctx,dx,dy,image->width,image->height,dcMem,0,0,image->width,image->height,bf);
989 */
990 }
991 image->ReleaseDC(dcMem);
992 }
993
994
995 // Draw bitmap
drawBitmap(const FXBitmap * bitmap,FXint dx,FXint dy)996 void FXDCWindow::drawBitmap(const FXBitmap* bitmap,FXint dx,FXint dy) {
997 if(!surface) fxerror("FXDCWindow::drawBitmap: DC not connected to drawable.\n");
998 if(!bitmap || !bitmap->id()) fxerror("FXDCWindow::drawBitmap: illegal bitmap specified.\n");
999 HDC dcMem=(HDC)bitmap->GetDC();
1000 switch(rop){
1001 case BLT_CLR: // D := 0
1002 ::BitBlt((HDC)ctx,dx,dy,bitmap->width,bitmap->height,dcMem,0,0,BLACKNESS);
1003 break;
1004 case BLT_SRC_AND_DST: // D := S & D
1005 ::BitBlt((HDC)ctx,dx,dy,bitmap->width,bitmap->height,dcMem,0,0,SRCAND);
1006 break;
1007 case BLT_SRC_AND_NOT_DST: // D := S & ~D
1008 ::BitBlt((HDC)ctx,dx,dy,bitmap->width,bitmap->height,dcMem,0,0,SRCERASE);
1009 break;
1010 case BLT_SRC: // D := S
1011 ::BitBlt((HDC)ctx,dx,dy,bitmap->width,bitmap->height,dcMem,0,0,SRCCOPY);
1012 break;
1013 case BLT_NOT_SRC_AND_DST: // D := ~S & D
1014 ::BitBlt((HDC)ctx,dx,dy,bitmap->width,bitmap->height,dcMem,0,0,0x220326);
1015 break;
1016 case BLT_DST: // D := D
1017 break;
1018 case BLT_SRC_XOR_DST: // D := S ^ D
1019 ::BitBlt((HDC)ctx,dx,dy,bitmap->width,bitmap->height,dcMem,0,0,SRCINVERT);
1020 break;
1021 case BLT_SRC_OR_DST: // D := S | D
1022 ::BitBlt((HDC)ctx,dx,dy,bitmap->width,bitmap->height,dcMem,0,0,SRCPAINT);
1023 break;
1024 case BLT_NOT_SRC_AND_NOT_DST: // D := ~S & ~D == D := ~(S | D)
1025 ::BitBlt((HDC)ctx,dx,dy,bitmap->width,bitmap->height,dcMem,0,0,NOTSRCERASE);
1026 break;
1027 case BLT_NOT_SRC_XOR_DST: // D := ~S ^ D
1028 ::BitBlt((HDC)ctx,dx,dy,bitmap->width,bitmap->height,dcMem,0,0,0x990066); // Not sure about this one
1029 break;
1030 case BLT_NOT_DST: // D := ~D
1031 ::BitBlt((HDC)ctx,dx,dy,bitmap->width,bitmap->height,dcMem,0,0,DSTINVERT);
1032 break;
1033 case BLT_SRC_OR_NOT_DST: // D := S | ~D
1034 ::BitBlt((HDC)ctx,dx,dy,bitmap->width,bitmap->height,dcMem,0,0,0xDD0228);
1035 break;
1036 case BLT_NOT_SRC: // D := ~S
1037 ::BitBlt((HDC)ctx,dx,dy,bitmap->width,bitmap->height,dcMem,0,0,NOTSRCCOPY);
1038 break;
1039 case BLT_NOT_SRC_OR_DST: // D := ~S | D
1040 ::BitBlt((HDC)ctx,dx,dy,bitmap->width,bitmap->height,dcMem,0,0,MERGEPAINT);
1041 break;
1042 case BLT_NOT_SRC_OR_NOT_DST: // D := ~S | ~D == ~(S & D)
1043 ::BitBlt((HDC)ctx,dx,dy,bitmap->width,bitmap->height,dcMem,0,0,0x7700E6);
1044 break;
1045 case BLT_SET: // D := 1
1046 ::BitBlt((HDC)ctx,dx,dy,bitmap->width,bitmap->height,dcMem,0,0,WHITENESS);
1047 break;
1048 }
1049 bitmap->ReleaseDC(dcMem);
1050 }
1051
1052
1053 // Draw icon
drawIcon(const FXIcon * icon,FXint dx,FXint dy)1054 void FXDCWindow::drawIcon(const FXIcon* icon,FXint dx,FXint dy){
1055 if(!surface){ fxerror("FXDCWindow::drawIcon: DC not connected to drawable.\n"); }
1056 if(!icon || !icon->id() || !icon->shape){ fxerror("FXDCWindow::drawIcon: illegal icon specified.\n"); }
1057 HDC hdcsrc=(HDC)icon->GetDC();
1058 if(icon->getOptions()&IMAGE_OPAQUE){
1059 ::BitBlt((HDC)ctx,dx,dy,icon->getWidth(),icon->getHeight(),hdcsrc,0,0,SRCCOPY);
1060 }
1061 else{
1062 HDC hdcmsk=::CreateCompatibleDC((HDC)ctx);
1063 HBITMAP holdbmp=(HBITMAP)::SelectObject(hdcmsk,(HBITMAP)icon->shape);
1064 COLORREF coldback=::SetBkColor((HDC)ctx,RGB(255,255,255));
1065 COLORREF coldtext=::SetTextColor((HDC)ctx,RGB(0,0,0));
1066 ::BitBlt((HDC)ctx,dx,dy,icon->getWidth(),icon->getHeight(),hdcmsk,0,0,SRCAND);
1067 ::BitBlt((HDC)ctx,dx,dy,icon->getWidth(),icon->getHeight(),hdcsrc,0,0,SRCPAINT);
1068 ::SelectObject(hdcmsk,holdbmp);
1069 ::DeleteDC(hdcmsk);
1070 ::SetBkColor((HDC)ctx,coldback);
1071 ::SetTextColor((HDC)ctx,coldtext);
1072 }
1073 icon->ReleaseDC(hdcsrc);
1074 }
1075
1076
1077 // This may be done faster, I suspect; but I'm tired of looking at this now;
1078 // at least it's correct as it stands..
drawIconShaded(const FXIcon * icon,FXint dx,FXint dy)1079 void FXDCWindow::drawIconShaded(const FXIcon* icon,FXint dx,FXint dy){
1080 if(!surface){ fxerror("FXDCWindow::drawIconShaded: DC not connected to drawable.\n"); }
1081 if(!icon || !icon->id() || !icon->shape){ fxerror("FXDCWindow::drawIconShaded: illegal icon specified.\n"); }
1082 FXColor selbackColor=getApp()->getSelbackColor();
1083 HDC hdcsrc=(HDC)icon->GetDC();
1084 HDC hdcmsk=::CreateCompatibleDC((HDC)ctx);
1085
1086 // Set shape mask
1087 HBITMAP holdbmp=(HBITMAP)::SelectObject(hdcmsk,(HBITMAP)icon->shape);
1088
1089 // Set colors
1090 COLORREF coldback=::SetBkColor((HDC)ctx,RGB(255,255,255));
1091 COLORREF coldtext=::SetTextColor((HDC)ctx,RGB(0,0,0));
1092
1093 // Paint icon
1094 ::BitBlt((HDC)ctx,dx,dy,icon->getWidth(),icon->getHeight(),hdcmsk,0,0,SRCAND);
1095 ::BitBlt((HDC)ctx,dx,dy,icon->getWidth(),icon->getHeight(),hdcsrc,0,0,SRCPAINT);
1096
1097 // Select brush
1098 HBRUSH hbrush=::CreatePatternBrush((HBITMAP)getApp()->stipples[STIPPLE_GRAY]);
1099 HBRUSH holdbrush=(HBRUSH)::SelectObject((HDC)ctx,hbrush);
1100 ::SetBrushOrgEx((HDC)ctx,dx,dy,NULL);
1101
1102 // Make black where pattern is 0 and shape is 0 [DPSoa]
1103 ::BitBlt((HDC)ctx,dx,dy,icon->getWidth(),icon->getHeight(),hdcmsk,0,0,0x00A803A9);
1104
1105 // Set colors
1106 ::SetTextColor((HDC)ctx,RGB(FXREDVAL(selbackColor),FXGREENVAL(selbackColor),FXBLUEVAL(selbackColor)));
1107 ::SetBkColor((HDC)ctx,RGB(0,0,0));
1108
1109 // Make selbackcolor where pattern is 0 and shape is 0 [DPSoo]
1110 ::BitBlt((HDC)ctx,dx,dy,icon->getWidth(),icon->getHeight(),hdcmsk,0,0,0x00FE02A9);
1111
1112 // Resetore ctx
1113 ::SelectObject(hdcmsk,holdbmp);
1114 ::DeleteDC(hdcmsk);
1115 ::SelectObject((HDC)ctx,holdbrush);
1116 ::DeleteObject(hbrush);
1117 ::SetBkColor((HDC)ctx,coldback);
1118 ::SetTextColor((HDC)ctx,coldtext);
1119 ::SetBrushOrgEx((HDC)ctx,tx,ty,NULL);
1120 icon->ReleaseDC(hdcsrc);
1121 }
1122
1123
1124
1125 // Draw a sunken or etched-in icon.
drawIconSunken(const FXIcon * icon,FXint dx,FXint dy)1126 void FXDCWindow::drawIconSunken(const FXIcon* icon,FXint dx,FXint dy){
1127 if(!surface){ fxerror("FXDCWindow::drawIconSunken: DC not connected to drawable.\n"); }
1128 if(!icon || !icon->id() || !icon->shape){ fxerror("FXDCWindow::drawIconSunken: illegal icon specified.\n"); }
1129 FXColor shadowColor=getApp()->getShadowColor();
1130 FXColor hiliteColor=getApp()->getHiliteColor();
1131 HDC hdcsrc=(HDC)icon->GetDC();
1132 HDC hdcmono=::CreateCompatibleDC((HDC)ctx);
1133
1134 // Set etch mask
1135 HBITMAP holdbmp=(HBITMAP)::SelectObject(hdcmono,(HBITMAP)icon->etch);
1136
1137 // Set colors
1138 COLORREF coldback=::SetBkColor((HDC)ctx,RGB(255,255,255));
1139 COLORREF coldtext=::SetTextColor((HDC)ctx,RGB(0,0,0));
1140
1141 // While brush colors apply to the pattern
1142 HBRUSH hbrhilite=::CreateSolidBrush(RGB(FXREDVAL(hiliteColor),FXGREENVAL(hiliteColor),FXBLUEVAL(hiliteColor)));
1143 HBRUSH holdbrush=(HBRUSH)::SelectObject((HDC)ctx,hbrhilite);
1144
1145 // BitBlt the black bits in the monochrome bitmap into highlight colors
1146 // in the destination DC (offset a bit). This BitBlt(), and the next one,
1147 // use an unnamed raster op (0xB8074a) whose effect is D := ((D ^ P) & S) ^ P.
1148 // Or at least I think it is ;) The code = PSDPxax, so that's correct JVZ
1149 ::BitBlt((HDC)ctx,dx+1,dy+1,icon->getWidth(),icon->getHeight(),hdcmono,0,0,0xB8074A);
1150 HBRUSH hbrshadow=::CreateSolidBrush(RGB(FXREDVAL(shadowColor),FXGREENVAL(shadowColor),FXBLUEVAL(shadowColor)));
1151 ::SelectObject((HDC)ctx,hbrshadow);
1152
1153 // Now BitBlt the black bits in the monochrome bitmap into the
1154 // shadow color on the destination DC.
1155 ::BitBlt((HDC)ctx,dx,dy,icon->getWidth(),icon->getHeight(),hdcmono,0,0,0xB8074A);
1156
1157 // Resetore ctx
1158 ::SelectObject(hdcmono,holdbmp);
1159 ::DeleteDC(hdcmono);
1160 ::SelectObject((HDC)ctx,holdbrush);
1161 ::DeleteObject(hbrhilite);
1162 ::DeleteObject(hbrshadow);
1163 ::SetBkColor((HDC)ctx,coldback);
1164 ::SetTextColor((HDC)ctx,coldtext);
1165 icon->ReleaseDC(hdcsrc);
1166 }
1167
1168
1169 // Draw hash box
drawHashBox(FXint x,FXint y,FXint w,FXint h,FXint b)1170 void FXDCWindow::drawHashBox(FXint x,FXint y,FXint w,FXint h,FXint b){
1171 if(!surface){ fxerror("FXDCWindow::drawHashBox: DC not connected to drawable.\n"); }
1172 HBRUSH hbrush=::CreatePatternBrush((HBITMAP)getApp()->stipples[STIPPLE_GRAY]);
1173 HBRUSH holdbrush=(HBRUSH)::SelectObject((HDC)ctx,hbrush);
1174 COLORREF coldback=::SetBkColor((HDC)ctx,RGB(255,255,255));
1175 COLORREF coldtext=::SetTextColor((HDC)ctx,RGB(0,0,0));
1176 ::PatBlt((HDC)ctx,x,y,w-b,b,PATINVERT);
1177 ::PatBlt((HDC)ctx,x+w-b,y,b,h-b,PATINVERT);
1178 ::PatBlt((HDC)ctx,x+b,y+h-b,w-b,b,PATINVERT);
1179 ::PatBlt((HDC)ctx,x,y+b,b,h-b,PATINVERT);
1180 ::SelectObject((HDC)ctx,holdbrush);
1181 ::DeleteObject(hbrush);
1182 ::SetBkColor((HDC)ctx,coldback);
1183 ::SetTextColor((HDC)ctx,coldtext);
1184 }
1185
1186
1187 // Draw focus rectangle
drawFocusRectangle(FXint x,FXint y,FXint w,FXint h)1188 void FXDCWindow::drawFocusRectangle(FXint x,FXint y,FXint w,FXint h){
1189 if(!surface){ fxerror("FXDCWindow::drawFocusRectangle: DC not connected to drawable.\n"); }
1190 HBRUSH hbrush=::CreatePatternBrush((HBITMAP)getApp()->stipples[STIPPLE_GRAY]);
1191 HBRUSH holdbrush=(HBRUSH)::SelectObject((HDC)ctx,hbrush);
1192 COLORREF coldback=::SetBkColor((HDC)ctx,RGB(255,255,255));
1193 COLORREF coldtext=::SetTextColor((HDC)ctx,RGB(0,0,0));
1194 ::SetBrushOrgEx((HDC)ctx,x,y,NULL);
1195 ::PatBlt((HDC)ctx,x,y,w-1,1,PATINVERT);
1196 ::PatBlt((HDC)ctx,x+w-1,y,1,h-1,PATINVERT);
1197 ::PatBlt((HDC)ctx,x+1,y+h-1,w-1,1,PATINVERT);
1198 ::PatBlt((HDC)ctx,x,y+1,1,h-1,PATINVERT);
1199 ::SelectObject((HDC)ctx,holdbrush);
1200 ::DeleteObject(hbrush);
1201 ::SetBkColor((HDC)ctx,coldback);
1202 ::SetTextColor((HDC)ctx,coldtext);
1203 ::SetBrushOrgEx((HDC)ctx,tx,ty,NULL);
1204 }
1205
1206
FXStipplePattern2Hatch(FXStipplePattern pat)1207 static DWORD FXStipplePattern2Hatch(FXStipplePattern pat){
1208 switch(pat){
1209 case STIPPLE_HORZ: return HS_HORIZONTAL;
1210 case STIPPLE_VERT: return HS_VERTICAL;
1211 case STIPPLE_CROSS: return HS_CROSS;
1212 case STIPPLE_DIAG: return HS_BDIAGONAL;
1213 case STIPPLE_REVDIAG: return HS_FDIAGONAL;
1214 case STIPPLE_CROSSDIAG: return HS_DIAGCROSS;
1215 default: return HS_CROSS;
1216 }
1217 }
1218
1219
updatePen()1220 void FXDCWindow::updatePen(){
1221 DWORD dashes[32];
1222 DWORD penstyle,i;
1223 LOGBRUSH lb;
1224
1225 // Setup brush of this pen
1226 switch(fill){
1227 case FILL_SOLID:
1228 lb.lbStyle=BS_SOLID;
1229 lb.lbColor=devfg;
1230 lb.lbHatch=0;
1231 break;
1232 case FILL_TILED:
1233 lb.lbStyle=BS_SOLID;
1234 lb.lbColor=devfg;
1235 lb.lbHatch=0;
1236 break;
1237 case FILL_STIPPLED:
1238 if(stipple){
1239 lb.lbStyle=BS_PATTERN;
1240 lb.lbColor=devfg;
1241 lb.lbHatch=(FXuval)stipple->id(); // This should be a HBITMAP
1242 }
1243 else if(pattern>=STIPPLE_0 && pattern<=STIPPLE_16){
1244 lb.lbStyle=BS_PATTERN;
1245 lb.lbColor=devfg;
1246 lb.lbHatch=(FXuval)getApp()->stipples[pattern];
1247 }
1248 else{
1249 lb.lbStyle=BS_HATCHED;
1250 lb.lbColor=devfg;
1251 lb.lbHatch=FXStipplePattern2Hatch(pattern);
1252 }
1253 break;
1254 case FILL_OPAQUESTIPPLED:
1255 if(stipple){
1256 lb.lbStyle=BS_PATTERN;
1257 lb.lbColor=devfg;
1258 lb.lbHatch=(FXuval)stipple->id(); // This should be a HBITMAP
1259 }
1260 else if(pattern>=STIPPLE_0 && pattern<=STIPPLE_16){
1261 lb.lbStyle=BS_PATTERN;
1262 lb.lbColor=devfg;
1263 lb.lbHatch=(FXuval)getApp()->stipples[pattern];
1264 }
1265 else{
1266 lb.lbStyle=BS_HATCHED;
1267 lb.lbColor=devfg;
1268 lb.lbHatch=FXStipplePattern2Hatch(pattern);
1269 }
1270 break;
1271 }
1272
1273 penstyle=0;
1274
1275 // Cap style
1276 if(cap==CAP_ROUND)
1277 penstyle|=PS_JOIN_ROUND;
1278 else if(cap==CAP_PROJECTING)
1279 penstyle|=PS_ENDCAP_SQUARE;
1280 else
1281 penstyle|=PS_ENDCAP_FLAT;
1282
1283 // Join style
1284 if(join==JOIN_MITER)
1285 penstyle|=PS_JOIN_MITER;
1286 else if(join==JOIN_ROUND)
1287 penstyle|=PS_JOIN_ROUND;
1288 else
1289 penstyle|=PS_JOIN_BEVEL;
1290
1291 // Kind of pen
1292 //if(width<=1 && fill==FILL_SOLID)
1293 // penstyle|=PS_COSMETIC;
1294 //else
1295 penstyle|=PS_GEOMETRIC;
1296
1297 // Line style
1298 if(style==LINE_SOLID){
1299 penstyle|=PS_SOLID;
1300 ::DeleteObject(::SelectObject((HDC)ctx,::ExtCreatePen(penstyle,width,&lb,0,NULL)));
1301 }
1302 else if(dashoff==0 && dashlen==2 && dashpat[0]==1 && dashpat[1]==1){
1303 penstyle|=PS_DOT;
1304 ::DeleteObject(::SelectObject((HDC)ctx,::ExtCreatePen(penstyle,width,&lb,0,NULL)));
1305 }
1306 else if(dashoff==0 && dashlen==2 && dashpat[0]==3 && dashpat[1]==1){
1307 penstyle|=PS_DASH;
1308 ::DeleteObject(::SelectObject((HDC)ctx,::ExtCreatePen(penstyle,width,&lb,0,NULL)));
1309 }
1310 else if(dashoff==0 && dashlen==4 && dashpat[0]==3 && dashpat[1]==1 && dashpat[2]==1 && dashpat[3]==1){
1311 penstyle|=PS_DASHDOT;
1312 ::DeleteObject(::SelectObject((HDC)ctx,::ExtCreatePen(penstyle,width,&lb,0,NULL)));
1313 }
1314 else if(dashoff==0 && dashlen==6 && dashpat[0]==3 && dashpat[1]==1 && dashpat[2]==1 && dashpat[3]==1 && dashpat[4]==1 && dashpat[5]==1){
1315 penstyle|=PS_DASHDOTDOT;
1316 ::DeleteObject(::SelectObject((HDC)ctx,::ExtCreatePen(penstyle,width,&lb,0,NULL)));
1317 }
1318 else{
1319 penstyle|=PS_USERSTYLE;
1320 for(i=0; i<dashlen; i++){ dashes[i]=dashpat[(i+dashoff)%dashlen]; }
1321 ::DeleteObject(::SelectObject((HDC)ctx,::ExtCreatePen(penstyle,width,&lb,dashlen,dashes)));
1322 }
1323 if(fill==FILL_STIPPLED){
1324 ::SetBkMode((HDC)ctx,TRANSPARENT); // Alas, only works for BS_HATCHED...
1325 }
1326 else{
1327 ::SetBkMode((HDC)ctx,OPAQUE);
1328 }
1329 if(fill!=FILL_SOLID){
1330 ::SetBrushOrgEx((HDC)ctx,tx,ty,NULL);
1331 }
1332 needsPath=(width>1);
1333 needsNewPen=false;
1334 }
1335
1336
updateBrush()1337 void FXDCWindow::updateBrush(){
1338 LOGBRUSH lb;
1339 switch(fill){
1340 case FILL_SOLID:
1341 lb.lbStyle=BS_SOLID;
1342 lb.lbColor=devfg;
1343 lb.lbHatch=0;
1344 ::DeleteObject(::SelectObject((HDC)ctx,::CreateBrushIndirect(&lb)));
1345 break;
1346 case FILL_TILED:
1347 if(tile){
1348 ::DeleteObject(::SelectObject((HDC)ctx,::CreatePatternBrush((HBITMAP)tile->id())));
1349 }
1350 else{
1351 lb.lbStyle=BS_SOLID;
1352 lb.lbColor=devfg;
1353 lb.lbHatch=0;
1354 ::DeleteObject(::SelectObject((HDC)ctx,::CreateBrushIndirect(&lb)));
1355 }
1356 break;
1357 case FILL_STIPPLED:
1358 if(stipple){
1359 lb.lbStyle=BS_PATTERN;
1360 lb.lbColor=devfg;
1361 lb.lbHatch=(FXuval)stipple->id(); // This should be a HBITMAP
1362 }
1363 else if(pattern>=STIPPLE_0 && pattern<=STIPPLE_16){
1364 lb.lbStyle=BS_PATTERN;
1365 lb.lbColor=devfg;
1366 lb.lbHatch=(FXuval)getApp()->stipples[pattern];
1367 }
1368 else{
1369 lb.lbStyle=BS_HATCHED;
1370 lb.lbColor=devfg;
1371 lb.lbHatch=FXStipplePattern2Hatch(pattern);
1372 }
1373 ::DeleteObject(::SelectObject((HDC)ctx,::CreateBrushIndirect(&lb)));
1374 break;
1375 case FILL_OPAQUESTIPPLED:
1376 if(stipple){
1377 lb.lbStyle=BS_PATTERN;
1378 lb.lbColor=devfg;
1379 lb.lbHatch=(FXuval)stipple->id(); // This should be a HBITMAP
1380 }
1381 else if(pattern>=STIPPLE_0 && pattern<=STIPPLE_16){
1382 lb.lbStyle=BS_PATTERN;
1383 lb.lbColor=devfg;
1384 lb.lbHatch=(FXuval)getApp()->stipples[pattern];
1385 }
1386 else{
1387 lb.lbStyle=BS_HATCHED;
1388 lb.lbColor=devfg;
1389 lb.lbHatch=FXStipplePattern2Hatch(pattern);
1390 }
1391 ::DeleteObject(::SelectObject((HDC)ctx,::CreateBrushIndirect(&lb)));
1392 break;
1393 }
1394 if(fill==FILL_STIPPLED){
1395 ::SetBkMode((HDC)ctx,TRANSPARENT); // Alas, only works for BS_HATCHED...
1396 }
1397 else{
1398 ::SetBkMode((HDC)ctx,OPAQUE);
1399 }
1400 if(fill!=FILL_SOLID){
1401 ::SetBrushOrgEx((HDC)ctx,tx,ty,NULL);
1402 }
1403 needsNewBrush=false;
1404 }
1405
1406
1407 // Set foreground color
setForeground(FXColor clr)1408 void FXDCWindow::setForeground(FXColor clr){
1409 if(!surface){ fxerror("FXDCWindow::setForeground: DC not connected to drawable.\n"); }
1410 devfg=surface->visual->getPixel(clr);
1411 needsNewPen=true;
1412 needsNewBrush=true;
1413 ::SetTextColor((HDC)ctx,devfg);
1414 fg=clr;
1415 }
1416
1417
1418 // Set background color
setBackground(FXColor clr)1419 void FXDCWindow::setBackground(FXColor clr){
1420 if(!surface){ fxerror("FXDCWindow::setBackground: DC not connected to drawable.\n"); }
1421 devbg=surface->visual->getPixel(clr);
1422 ::SetBkColor((HDC)ctx,devbg);
1423 bg=clr;
1424 }
1425
1426
1427 // Set dash pattern (for the LINE_ONOFF_DASH line style)
setDashes(FXuint dashoffset,const FXchar * dashpattern,FXuint dashlength)1428 void FXDCWindow::setDashes(FXuint dashoffset,const FXchar *dashpattern,FXuint dashlength){
1429 FXuint len,i;
1430 if(!surface){ fxerror("FXDCWindow::setDashes: DC not connected to drawable.\n"); }
1431 if(dashlength>32){ fxerror("FXDCWindow::setDashes: bad dashlength parameter.\n"); }
1432 for(i=len=0; i<dashlength; i++){
1433 dashpat[i]=dashpattern[i];
1434 len+=(FXuint)dashpattern[i];
1435 }
1436 dashlen=dashlength;
1437 dashoff=dashoffset%len;
1438 needsNewPen=true;
1439 }
1440
1441
1442 // Set line width
setLineWidth(FXuint linewidth)1443 void FXDCWindow::setLineWidth(FXuint linewidth){
1444 if(!surface){ fxerror("FXDCWindow::setLineWidth: DC not connected to drawable.\n"); }
1445 width=linewidth;
1446 needsNewPen=true;
1447 }
1448
1449
1450 // Set line cap style
setLineCap(FXCapStyle capstyle)1451 void FXDCWindow::setLineCap(FXCapStyle capstyle){
1452 if(!surface){ fxerror("FXDCWindow::setLineCap: DC not connected to drawable.\n"); }
1453 cap=capstyle;
1454 needsNewPen=true;
1455 }
1456
1457
1458 // Set line join style
setLineJoin(FXJoinStyle joinstyle)1459 void FXDCWindow::setLineJoin(FXJoinStyle joinstyle){
1460 if(!surface){ fxerror("FXDCWindow::setLineJoin: DC not connected to drawable.\n"); }
1461 join=joinstyle;
1462 needsNewPen=true;
1463 }
1464
1465
1466 // Set line style
setLineStyle(FXLineStyle linestyle)1467 void FXDCWindow::setLineStyle(FXLineStyle linestyle){
1468 if(!surface){ fxerror("FXDCWindow::setLineStyle: DC not connected to drawable.\n"); }
1469 style=linestyle;
1470 needsNewPen=true;
1471 }
1472
1473
1474 // Set fill style
setFillStyle(FXFillStyle fillstyle)1475 void FXDCWindow::setFillStyle(FXFillStyle fillstyle){
1476 if(!surface){ fxerror("FXDCWindow::setFillStyle: DC not connected to drawable.\n"); }
1477 fill=fillstyle;
1478 needsNewBrush=true;
1479 needsNewPen=true;
1480 }
1481
1482
1483 // Set fill rule
setFillRule(FXFillRule fillrule)1484 void FXDCWindow::setFillRule(FXFillRule fillrule){
1485 if(!surface){ fxerror("FXDCWindow::setFillRule: DC not connected to drawable.\n"); }
1486 if(fillrule==RULE_EVEN_ODD)
1487 ::SetPolyFillMode((HDC)ctx,ALTERNATE);
1488 else
1489 ::SetPolyFillMode((HDC)ctx,WINDING);
1490 rule=fillrule;
1491 }
1492
1493
1494 // Set blit function
setFunction(FXFunction func)1495 void FXDCWindow::setFunction(FXFunction func){
1496 if(!surface){ fxerror("FXDCWindow::setFunction: DC not connected to drawable.\n"); }
1497 rop=func;
1498
1499 // Also set ROP2 code for lines
1500 switch(rop){
1501 case BLT_CLR: // D := 0
1502 ::SetROP2((HDC)ctx,R2_BLACK);
1503 break;
1504 case BLT_SRC_AND_DST: // D := S & D
1505 ::SetROP2((HDC)ctx,R2_MASKPEN);
1506 break;
1507 case BLT_SRC_AND_NOT_DST: // D := S & ~D
1508 ::SetROP2((HDC)ctx,R2_MASKPENNOT);
1509 break;
1510 case BLT_SRC: // D := S
1511 ::SetROP2((HDC)ctx,R2_COPYPEN);
1512 break;
1513 case BLT_NOT_SRC_AND_DST: // D := ~S & D
1514 ::SetROP2((HDC)ctx,R2_MASKNOTPEN);
1515 break;
1516 case BLT_DST: // D := D
1517 ::SetROP2((HDC)ctx,R2_NOP);
1518 break;
1519 case BLT_SRC_XOR_DST: // D := S ^ D
1520 ::SetROP2((HDC)ctx,R2_XORPEN);
1521 break;
1522 case BLT_SRC_OR_DST: // D := S | D
1523 ::SetROP2((HDC)ctx,R2_MERGEPEN);
1524 break;
1525 case BLT_NOT_SRC_AND_NOT_DST: // D := ~S & ~D == D := ~(S | D)
1526 ::SetROP2((HDC)ctx,R2_NOTMERGEPEN);
1527 break;
1528 case BLT_NOT_SRC_XOR_DST: // D := ~S ^ D
1529 ::SetROP2((HDC)ctx,R2_NOTXORPEN); // Is this the right one?
1530 break;
1531 case BLT_NOT_DST: // D := ~D
1532 ::SetROP2((HDC)ctx,R2_NOT);
1533 break;
1534 case BLT_SRC_OR_NOT_DST: // D := S | ~D
1535 ::SetROP2((HDC)ctx,R2_MERGEPENNOT);
1536 break;
1537 case BLT_NOT_SRC: // D := ~S
1538 ::SetROP2((HDC)ctx,R2_NOTCOPYPEN);
1539 break;
1540 case BLT_NOT_SRC_OR_DST: // D := ~S | D
1541 ::SetROP2((HDC)ctx,R2_MERGENOTPEN);
1542 break;
1543 case BLT_NOT_SRC_OR_NOT_DST: // D := ~S | ~D == ~(S & D)
1544 ::SetROP2((HDC)ctx,R2_NOTMASKPEN);
1545 break;
1546 case BLT_SET: // D := 1
1547 ::SetROP2((HDC)ctx,R2_WHITE);
1548 break;
1549 }
1550 }
1551
1552
1553 // Set tile image
setTile(FXImage * image,FXint dx,FXint dy)1554 void FXDCWindow::setTile(FXImage* image,FXint dx,FXint dy){
1555 if(!surface){ fxerror("FXDCWindow::setTile: DC not connected to drawable.\n"); }
1556 if(!image || !image->id()){ fxerror("FXDCWindow::setTile: illegal image specified.\n"); }
1557 tile=image;
1558 tx=dx;
1559 ty=dy;
1560 }
1561
1562
1563 // Set stipple pattern
setStipple(FXBitmap * bitmap,FXint dx,FXint dy)1564 void FXDCWindow::setStipple(FXBitmap* bitmap,FXint dx,FXint dy){
1565 if(!surface){ fxerror("FXDCWindow::setStipple: DC not connected to drawable.\n"); }
1566 if(!bitmap || !bitmap->id()){ fxerror("FXDCWindow::setStipple: illegal image specified.\n"); }
1567 stipple=bitmap;
1568 pattern=STIPPLE_NONE;
1569 needsNewBrush=true;
1570 needsNewPen=true;
1571 tx=dx;
1572 ty=dy;
1573 }
1574
1575
setStipple(FXStipplePattern pat,FXint dx,FXint dy)1576 void FXDCWindow::setStipple(FXStipplePattern pat,FXint dx,FXint dy){
1577 if(!surface){ fxerror("FXDCWindow::setStipple: DC not connected to drawable.\n"); }
1578 stipple=NULL;
1579 pattern=pat;
1580 needsNewBrush=true;
1581 needsNewPen=true;
1582 tx=dx;
1583 ty=dy;
1584 }
1585
1586
1587 // Patch from "Dimitris Servis" <servis@deslab.ntua.gr>
1588 // The new clip rectangle should be the intersect of the region
1589 // boundary rectangle and the paint rectangle.
1590 // Another patch from Ivan Markov <ivan.markov@wizcom.bg> to delete
1591 // the region which must be disposed off explicitly.
setClipRegion(const FXRegion & region)1592 void FXDCWindow::setClipRegion(const FXRegion& region){
1593 if(!surface){ fxerror("FXDCWindow::setClipRegion: DC not connected to drawable.\n"); }
1594 FXRectangle rectangle=region.bounds();
1595 clip.x=FXMAX(rectangle.x,rect.x);
1596 clip.y=FXMAX(rectangle.y,rect.y);
1597 clip.w=FXMIN(rectangle.x+rectangle.w,rect.x+rect.w)-clip.x;
1598 clip.h=FXMIN(rectangle.y+rectangle.h,rect.y+rect.h)-clip.y;
1599 if(clip.w<=0) clip.w=0;
1600 if(clip.h<=0) clip.h=0;
1601 HRGN hrgn=::CreateRectRgn(clip.x,clip.y,clip.x+clip.w,clip.y+clip.h);
1602 ::CombineRgn(hrgn,hrgn,(HRGN)region.region,RGN_AND);
1603 ::SelectClipRgn((HDC)ctx,hrgn);
1604 ::DeleteObject(hrgn);
1605 }
1606
1607
1608 // Set clip rectangle
setClipRectangle(FXint x,FXint y,FXint w,FXint h)1609 void FXDCWindow::setClipRectangle(FXint x,FXint y,FXint w,FXint h){
1610 if(!surface){ fxerror("FXDCWindow::setClipRectangle: DC not connected to drawable.\n"); }
1611 clip.x=FXMAX(x,rect.x);
1612 clip.y=FXMAX(y,rect.y);
1613 clip.w=FXMIN(x+w,rect.x+rect.w)-clip.x;
1614 clip.h=FXMIN(y+h,rect.y+rect.h)-clip.y;
1615 if(clip.w<=0) clip.w=0;
1616 if(clip.h<=0) clip.h=0;
1617 HRGN hrgn=::CreateRectRgn(clip.x,clip.y,clip.x+clip.w,clip.y+clip.h);
1618 ::SelectClipRgn((HDC)ctx,hrgn);
1619 ::DeleteObject(hrgn);
1620 }
1621
1622
1623 // Set clip rectangle
setClipRectangle(const FXRectangle & rectangle)1624 void FXDCWindow::setClipRectangle(const FXRectangle& rectangle){
1625 if(!surface){ fxerror("FXDCWindow::setClipRectangle: DC not connected to drawable.\n"); }
1626 clip.x=FXMAX(rectangle.x,rect.x);
1627 clip.y=FXMAX(rectangle.y,rect.y);
1628 clip.w=FXMIN(rectangle.x+rectangle.w,rect.x+rect.w)-clip.x;
1629 clip.h=FXMIN(rectangle.y+rectangle.h,rect.y+rect.h)-clip.y;
1630 if(clip.w<=0) clip.w=0;
1631 if(clip.h<=0) clip.h=0;
1632 HRGN hrgn=::CreateRectRgn(clip.x,clip.y,clip.x+clip.w,clip.y+clip.h);
1633 ::SelectClipRgn((HDC)ctx,hrgn);
1634 ::DeleteObject(hrgn);
1635 }
1636
1637
1638 // Clear clip rectangle
clearClipRectangle()1639 void FXDCWindow::clearClipRectangle(){
1640 if(!surface){ fxerror("FXDCWindow::clearClipRectangle: DC not connected to drawable.\n"); }
1641 clip=rect;
1642 HRGN hrgn=::CreateRectRgn(clip.x,clip.y,clip.x+clip.w,clip.y+clip.h);
1643 ::SelectClipRgn((HDC)ctx,hrgn);
1644 ::DeleteObject(hrgn);
1645 }
1646
1647
1648
1649 // Set clip mask
setClipMask(FXBitmap * bitmap,FXint dx,FXint dy)1650 void FXDCWindow::setClipMask(FXBitmap* bitmap,FXint dx,FXint dy){
1651 if(!surface){ fxerror("FXDCWindow::setClipMask: DC not connected to drawable.\n"); }
1652 if(!bitmap || !bitmap->id()){ fxerror("FXDCWindow::setClipMask: illegal mask specified.\n"); }
1653 FXASSERT(false);
1654 mask=bitmap;
1655 cx=dx;
1656 cy=dy;
1657 }
1658
1659
1660 // Clear clip mask
clearClipMask()1661 void FXDCWindow::clearClipMask(){
1662 if(!surface){ fxerror("FXDCWindow::clearClipMask: DC not connected to drawable.\n"); }
1663 FXASSERT(false);
1664 mask=NULL;
1665 cx=0;
1666 cy=0;
1667 }
1668
1669
1670 // Window will clip against child windows
clipChildren(FXbool yes)1671 void FXDCWindow::clipChildren(FXbool yes){
1672 if(!surface){ fxerror("FXDCWindow::clipChildren: window has not yet been created.\n"); }
1673 DWORD dwFlags=::GetWindowLong((HWND)surface->id(),GWL_STYLE);
1674 HPEN hPen;
1675 HBRUSH hBrush;
1676 HFONT hFont;
1677 COLORREF textcolor;
1678 COLORREF backcolor;
1679 FXint fillmode;
1680 if(yes){
1681 if(!(dwFlags&WS_CLIPCHILDREN)){
1682 if((HWND)surface->id()!=GetDesktopWindow()){
1683 hPen=(HPEN)SelectObject((HDC)ctx,::GetStockObject(NULL_PEN));
1684 hBrush=(HBRUSH)::SelectObject((HDC)ctx,::GetStockObject(NULL_BRUSH));
1685 hFont=(HFONT)::SelectObject((HDC)ctx,::GetStockObject(SYSTEM_FONT));
1686 textcolor=::GetTextColor((HDC)ctx);
1687 backcolor=::GetBkColor((HDC)ctx);
1688 fillmode=::GetPolyFillMode((HDC)ctx);
1689
1690 ::ReleaseDC((HWND)surface->id(),(HDC)ctx);
1691 ::SetWindowLong((HWND)surface->id(),GWL_STYLE,dwFlags|WS_CLIPCHILDREN);
1692 ctx=::GetDC((HWND)surface->id());
1693
1694 ::SelectObject((HDC)ctx,hFont);
1695 ::SelectObject((HDC)ctx,hPen);
1696 ::SelectObject((HDC)ctx,hBrush);
1697
1698 if(surface->visual->colormap){
1699 ::SelectPalette((HDC)ctx,(HPALETTE)surface->visual->colormap,false);
1700 ::RealizePalette((HDC)ctx);
1701 }
1702 ::SetTextAlign((HDC)ctx,TA_BASELINE|TA_LEFT);
1703 ::SetTextColor((HDC)ctx,textcolor);
1704 ::SetBkColor((HDC)ctx,backcolor);
1705 ::SetPolyFillMode((HDC)ctx,fillmode);
1706 needsClipReset=false;
1707 }
1708 }
1709 }
1710 else{
1711 if(dwFlags&WS_CLIPCHILDREN){
1712 if((HWND)surface->id()!=GetDesktopWindow()){
1713 hPen=(HPEN)::SelectObject((HDC)ctx,::GetStockObject(NULL_PEN));
1714 hBrush=(HBRUSH)::SelectObject((HDC)ctx,::GetStockObject(NULL_BRUSH));
1715 hFont=(HFONT)::SelectObject((HDC)ctx,::GetStockObject(SYSTEM_FONT));
1716 textcolor=::GetTextColor((HDC)ctx);
1717 backcolor=::GetBkColor((HDC)ctx);
1718 fillmode=::GetPolyFillMode((HDC)ctx);
1719
1720 ::ReleaseDC((HWND)surface->id(),(HDC)ctx);
1721 ::SetWindowLong((HWND)surface->id(),GWL_STYLE,dwFlags&~WS_CLIPCHILDREN);
1722 ctx=::GetDC((HWND)surface->id());
1723
1724 ::SelectObject((HDC)ctx,hFont);
1725 ::SelectObject((HDC)ctx,hPen);
1726 ::SelectObject((HDC)ctx,hBrush);
1727
1728 if(surface->visual->colormap){
1729 ::SelectPalette((HDC)ctx,(HPALETTE)surface->visual->colormap,false);
1730 ::RealizePalette((HDC)ctx);
1731 }
1732 ::SetTextAlign((HDC)ctx,TA_BASELINE|TA_LEFT);
1733 ::SetTextColor((HDC)ctx,textcolor);
1734 ::SetBkColor((HDC)ctx,backcolor);
1735 ::SetPolyFillMode((HDC)ctx,fillmode);
1736 needsClipReset=true;
1737 }
1738 }
1739 }
1740 }
1741
1742 /********************************************************************************
1743 * X-Windows *
1744 ********************************************************************************/
1745
1746 #else
1747
1748
1749 // Construct for expose event painting
1750 FXDCWindow::FXDCWindow(FXDrawable* draw,FXEvent* event):FXDC(draw->getApp()),surface(NULL),rect(0,0,0,0),devfg(0),devbg(0){
1751 #ifdef HAVE_XFT_H
1752 xftDraw=NULL;
1753 #endif
1754 begin(draw);
1755 rect.x=clip.x=event->rect.x;
1756 rect.y=clip.y=event->rect.y;
1757 rect.w=clip.w=event->rect.w;
1758 rect.h=clip.h=event->rect.h;
1759 XSetClipRectangles((Display*)getApp()->getDisplay(),(GC)ctx,0,0,(XRectangle*)(void*)&clip,1,Unsorted);
1760 #ifdef HAVE_XFT_H
1761 XftDrawSetClipRectangles((XftDraw*)xftDraw,0,0,(XRectangle*)(void*)&clip,1);
1762 #endif
1763 flags|=GCClipMask;
1764 }
1765
1766
1767 // Construct for normal painting
1768 FXDCWindow::FXDCWindow(FXDrawable* draw):FXDC(draw->getApp()),surface(NULL),rect(0,0,0,0),devfg(0),devbg(0){
1769 #ifdef HAVE_XFT_H
1770 xftDraw=NULL;
1771 #endif
1772 begin(draw);
1773 }
1774
1775
1776 // Destruct
1777 FXDCWindow::~FXDCWindow(){
1778 end();
1779 }
1780
1781
1782 // Begin locks in a drawable surface
1783 void FXDCWindow::begin(FXDrawable *draw){
1784 if(!draw){ fxerror("FXDCWindow::begin: NULL drawable.\n"); }
1785 if(!draw->id()){ fxerror("FXDCWindow::begin: drawable not created yet.\n"); }
1786 surface=draw;
1787 rect.x=clip.x=0;
1788 rect.y=clip.y=0;
1789 rect.w=clip.w=draw->getWidth();
1790 rect.h=clip.h=draw->getHeight();
1791 devfg=~0;
1792 devbg=0;
1793 ctx=surface->visual->gc;
1794 flags=0;
1795 #ifdef HAVE_XFT_H
1796 xftDraw=(void*)XftDrawCreate((Display*)getApp()->getDisplay(),(Drawable)surface->id(),(Visual*)surface->visual->visual,(Colormap)surface->visual->colormap);
1797 #endif
1798 }
1799
1800
1801 // End unlock the drawable surface; restore it
1802 void FXDCWindow::end(){
1803 if(flags){
1804 XGCValues gcv;
1805 if(flags&GCFunction) gcv.function=BLT_SRC;
1806 if(flags&GCForeground) gcv.foreground=BlackPixel((Display*)getApp()->getDisplay(),DefaultScreen((Display*)getApp()->getDisplay()));
1807 if(flags&GCBackground) gcv.background=WhitePixel((Display*)getApp()->getDisplay(),DefaultScreen((Display*)getApp()->getDisplay()));
1808 if(flags&GCLineWidth) gcv.line_width=0;
1809 if(flags&GCCapStyle) gcv.cap_style=CAP_BUTT;
1810 if(flags&GCJoinStyle) gcv.join_style=JOIN_MITER;
1811 if(flags&GCLineStyle) gcv.line_style=LINE_SOLID;
1812 if(flags&GCFillStyle) gcv.fill_style=FILL_SOLID;
1813 if(flags&GCStipple) gcv.stipple=getApp()->stipples[STIPPLE_WHITE]; // Needed for IRIX6.4 bug workaround!
1814 if(flags&GCFillRule) gcv.fill_rule=RULE_EVEN_ODD;
1815 #ifndef HAVE_XFT_H
1816 if(flags&GCFont) gcv.font=getApp()->getNormalFont()->id();
1817 #endif
1818 if(flags&GCClipMask) gcv.clip_mask=None;
1819 if(flags&GCClipXOrigin) gcv.clip_x_origin=0;
1820 if(flags&GCClipYOrigin) gcv.clip_y_origin=0;
1821 if(flags&GCDashOffset) gcv.dash_offset=0;
1822 if(flags&GCDashList) gcv.dashes=4;
1823 if(flags&GCTileStipXOrigin) gcv.ts_x_origin=0;
1824 if(flags&GCTileStipYOrigin) gcv.ts_y_origin=0;
1825 if(flags&GCGraphicsExposures) gcv.graphics_exposures=True;
1826 if(flags&GCSubwindowMode) gcv.subwindow_mode=ClipByChildren;
1827 XChangeGC((Display*)getApp()->getDisplay(),(GC)ctx,flags,&gcv);
1828 flags=0;
1829 }
1830 surface=NULL;
1831 #ifdef HAVE_XFT_H
1832 if(xftDraw){
1833 XftDrawDestroy((XftDraw*)xftDraw);
1834 xftDraw=NULL;
1835 }
1836 #endif
1837 }
1838
1839
1840 // Read back pixel
1841 FXColor FXDCWindow::readPixel(FXint x,FXint y){
1842 FXColor color=FXRGBA(0,0,0,0);
1843 if(!surface){ fxerror("FXDCWindow::readPixel: DC not connected to drawable.\n"); }
1844 if(0<=x && 0<=y && x<surface->getWidth() && y<surface->getHeight()){
1845 XImage* xim=XGetImage((Display*)getApp()->getDisplay(),surface->id(),x,y,1,1,AllPlanes,ZPixmap);
1846 if(xim && xim->data){
1847 color=surface->visual->getColor(XGetPixel(xim,0,0));
1848 XDestroyImage(xim);
1849 }
1850 }
1851 return color;
1852 }
1853
1854
1855 // Draw point
1856 void FXDCWindow::drawPoint(FXint x,FXint y){
1857 if(!surface){ fxerror("FXDCWindow::drawPoint: DC not connected to drawable.\n"); }
1858 XDrawPoint((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,x,y);
1859 }
1860
1861
1862 // Draw points
1863 void FXDCWindow::drawPoints(const FXPoint* points,FXuint npoints){
1864 if(!surface){ fxerror("FXDCWindow::drawPoints: DC not connected to drawable.\n"); }
1865 XDrawPoints((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,(XPoint*)points,npoints,CoordModeOrigin);
1866 }
1867
1868
1869 // Draw points relative
1870 void FXDCWindow::drawPointsRel(const FXPoint* points,FXuint npoints){
1871 if(!surface){ fxerror("FXDCWindow::drawPointsRel: DC not connected to drawable.\n"); }
1872 XDrawPoints((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,(XPoint*)points,npoints,CoordModePrevious);
1873 }
1874
1875
1876 // Draw line
1877 void FXDCWindow::drawLine(FXint x1,FXint y1,FXint x2,FXint y2){
1878 if(!surface){ fxerror("FXDCWindow::drawLine: DC not connected to drawable.\n"); }
1879 XDrawLine((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,x1,y1,x2,y2);
1880 }
1881
1882
1883 // Draw lines
1884 void FXDCWindow::drawLines(const FXPoint* points,FXuint npoints){
1885 if(!surface){ fxerror("FXDCWindow::drawLines: DC not connected to drawable.\n"); }
1886 XDrawLines((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,(XPoint*)points,npoints,CoordModeOrigin);
1887 }
1888
1889
1890 // Draw lines relative
1891 void FXDCWindow::drawLinesRel(const FXPoint* points,FXuint npoints){
1892 if(!surface){ fxerror("FXDCWindow::drawLinesRel: DC not connected to drawable.\n"); }
1893 XDrawLines((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,(XPoint*)points,npoints,CoordModePrevious);
1894 }
1895
1896
1897 // Draw line segments
1898 void FXDCWindow::drawLineSegments(const FXSegment* segments,FXuint nsegments){
1899 if(!surface){ fxerror("FXDCWindow::drawLineSegments: DC not connected to drawable.\n"); }
1900 XDrawSegments((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,(XSegment*)segments,nsegments);
1901 }
1902
1903
1904 // Draw rectangle
1905 void FXDCWindow::drawRectangle(FXint x,FXint y,FXint w,FXint h){
1906 if(!surface){ fxerror("FXDCWindow::drawRectangle: DC not connected to drawable.\n"); }
1907 XDrawRectangle((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,x,y,w,h);
1908 }
1909
1910
1911 // Draw rectangles
1912 void FXDCWindow::drawRectangles(const FXRectangle* rectangles,FXuint nrectangles){
1913 if(!surface){ fxerror("FXDCWindow::drawRectangles: DC not connected to drawable.\n"); }
1914 XDrawRectangles((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,(XRectangle*)rectangles,nrectangles);
1915 }
1916
1917
1918 // Draw round rectangle
1919 void FXDCWindow::drawRoundRectangle(FXint x,FXint y,FXint w,FXint h,FXint ew,FXint eh){
1920 XArc arcs[4]; XSegment segs[4]; XGCValues gcv;
1921 if(!surface){ fxerror("FXDCWindow::drawRoundRectangle: DC not connected to drawable.\n"); }
1922 if(ew+ew>w) ew=w>>1;
1923 if(eh+eh>h) eh=h>>1;
1924 arcs[0].x=arcs[2].x=x;
1925 arcs[0].y=arcs[1].y=y;
1926 arcs[1].x=arcs[3].x=x+w-(ew<<1);
1927 arcs[2].y=arcs[3].y=y+h-(eh<<1);
1928 arcs[0].width=arcs[1].width=arcs[2].width=arcs[3].width=ew<<1;
1929 arcs[0].height=arcs[1].height=arcs[2].height=arcs[3].height=eh<<1;
1930 arcs[0].angle1=5760;
1931 arcs[0].angle2=5760;
1932 arcs[1].angle1=0;
1933 arcs[1].angle2=5760;
1934 arcs[2].angle1=11520;
1935 arcs[2].angle2=5760;
1936 arcs[3].angle1=17280;
1937 arcs[3].angle2=5760;
1938 segs[0].x1=segs[1].x1=x+ew;
1939 segs[0].x2=segs[1].x2=x+w-ew;
1940 segs[0].y1=segs[0].y2=y;
1941 segs[1].y1=segs[1].y2=y+h;
1942 segs[2].x1=segs[2].x2=x;
1943 segs[3].x1=segs[3].x2=x+w;
1944 segs[2].y1=segs[3].y1=y+eh;
1945 segs[2].y2=segs[3].y2=y+h-eh;
1946 gcv.cap_style=CapButt;
1947 XChangeGC((Display*)getApp()->getDisplay(),(GC)ctx,GCCapStyle,&gcv);
1948 XDrawArcs((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,arcs,4);
1949 XDrawSegments((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,segs,4);
1950 gcv.cap_style=cap;
1951 XChangeGC((Display*)getApp()->getDisplay(),(GC)ctx,GCCapStyle,&gcv);
1952 }
1953
1954
1955 // Draw arc
1956 void FXDCWindow::drawArc(FXint x,FXint y,FXint w,FXint h,FXint ang1,FXint ang2){
1957 if(!surface){ fxerror("FXDCWindow::drawArc: DC not connected to drawable.\n"); }
1958 XDrawArc((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,x,y,w,h,ang1,ang2);
1959 }
1960
1961
1962 // Draw arcs
1963 void FXDCWindow::drawArcs(const FXArc* arcs,FXuint narcs){
1964 if(!surface){ fxerror("FXDCWindow::drawArcs: DC not connected to drawable.\n"); }
1965 XDrawArcs((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,(XArc*)arcs,narcs);
1966 }
1967
1968
1969 // Draw ellipse
1970 void FXDCWindow::drawEllipse(FXint x,FXint y,FXint w,FXint h){
1971 if(!surface){ fxerror("FXDCWindow::drawEllipse: DC not connected to drawable.\n"); }
1972 XDrawArc((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,x,y,w,h,0,23040);
1973 }
1974
1975
1976 // Fill rectangle
1977 void FXDCWindow::fillRectangle(FXint x,FXint y,FXint w,FXint h){
1978 if(!surface){ fxerror("FXDCWindow::fillRectangle: DC not connected to drawable.\n"); }
1979 XFillRectangle((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,x,y,w,h);
1980 }
1981
1982
1983 // Fill rectangles
1984 void FXDCWindow::fillRectangles(const FXRectangle* rectangles,FXuint nrectangles){
1985 if(!surface){ fxerror("FXDCWindow::fillRectangles: DC not connected to drawable.\n"); }
1986 XFillRectangles((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,(XRectangle*)rectangles,nrectangles);
1987 }
1988
1989
1990 // Fill rounded rectangle
1991 void FXDCWindow::fillRoundRectangle(FXint x,FXint y,FXint w,FXint h,FXint ew,FXint eh){
1992 XArc arcs[4]; XRectangle recs[3];
1993 if(!surface){ fxerror("FXDCWindow::fillRoundRectangle: DC not connected to drawable.\n"); }
1994 if(ew+ew>w) ew=w>>1;
1995 if(eh+eh>h) eh=h>>1;
1996 arcs[0].x=arcs[2].x=x;
1997 arcs[0].y=arcs[1].y=y;
1998 arcs[1].x=arcs[3].x=x+w-(ew<<1);
1999 arcs[2].y=arcs[3].y=y+h-(eh<<1);
2000 arcs[0].width=arcs[1].width=arcs[2].width=arcs[3].width=ew<<1;
2001 arcs[0].height=arcs[1].height=arcs[2].height=arcs[3].height=eh<<1;
2002 arcs[0].angle1=5760;
2003 arcs[0].angle2=5760;
2004 arcs[1].angle1=0;
2005 arcs[1].angle2=5760;
2006 arcs[2].angle1=11520;
2007 arcs[2].angle2=5760;
2008 arcs[3].angle1=17280;
2009 arcs[3].angle2=5760;
2010 recs[0].x=recs[2].x=x+ew;
2011 recs[0].width=recs[2].width=w-(ew<<1);
2012 recs[0].height=recs[2].height=eh;
2013 recs[0].y=y;
2014 recs[2].y=y+h-eh;
2015 recs[1].x=x;
2016 recs[1].y=y+eh;
2017 recs[1].width=w;
2018 recs[1].height=h-(eh<<1);
2019 XFillArcs((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,arcs,4);
2020 XFillRectangles((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,recs,3);
2021 }
2022
2023
2024 // Fill chord
2025 void FXDCWindow::fillChord(FXint x,FXint y,FXint w,FXint h,FXint ang1,FXint ang2){
2026 if(!surface){ fxerror("FXDCWindow::fillChord: DC not connected to drawable.\n"); }
2027 XSetArcMode((Display*)getApp()->getDisplay(),(GC)ctx,ArcChord);
2028 XFillArc((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,x,y,w,h,ang1,ang2);
2029 XSetArcMode((Display*)getApp()->getDisplay(),(GC)ctx,ArcPieSlice);
2030 }
2031
2032
2033 // Fill chords
2034 void FXDCWindow::fillChords(const FXArc* chords,FXuint nchords){
2035 if(!surface){ fxerror("FXDCWindow::fillChords: DC not connected to drawable.\n"); }
2036 XSetArcMode((Display*)getApp()->getDisplay(),(GC)ctx,ArcChord);
2037 XFillArcs((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,(XArc*)chords,nchords);
2038 XSetArcMode((Display*)getApp()->getDisplay(),(GC)ctx,ArcPieSlice);
2039 }
2040
2041
2042 // Fill arc
2043 void FXDCWindow::fillArc(FXint x,FXint y,FXint w,FXint h,FXint ang1,FXint ang2){
2044 if(!surface){ fxerror("FXDCWindow::fillArc: DC not connected to drawable.\n"); }
2045 XFillArc((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,x,y,w,h,ang1,ang2);
2046 }
2047
2048
2049 // Fill arcs
2050 void FXDCWindow::fillArcs(const FXArc* arcs,FXuint narcs){
2051 if(!surface){ fxerror("FXDCWindow::fillArcs: DC not connected to drawable.\n"); }
2052 XFillArcs((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,(XArc*)arcs,narcs);
2053 }
2054
2055
2056 // Fill ellipse
2057 void FXDCWindow::fillEllipse(FXint x,FXint y,FXint w,FXint h){
2058 if(!surface){ fxerror("FXDCWindow::fillEllipse: DC not connected to drawable.\n"); }
2059 XFillArc((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,x,y,w,h,0,23040);
2060 }
2061
2062
2063 // Fill polygon
2064 void FXDCWindow::fillPolygon(const FXPoint* points,FXuint npoints){
2065 if(!surface){ fxerror("FXDCWindow::fillArcs: DC not connected to drawable.\n"); }
2066 XFillPolygon((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,(XPoint*)points,npoints,Convex,CoordModeOrigin);
2067 }
2068
2069
2070 // Fill concave polygon
2071 void FXDCWindow::fillConcavePolygon(const FXPoint* points,FXuint npoints){
2072 if(!surface){ fxerror("FXDCWindow::fillConcavePolygon: DC not connected to drawable.\n"); }
2073 XFillPolygon((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,(XPoint*)points,npoints,Nonconvex,CoordModeOrigin);
2074 }
2075
2076
2077 // Fill complex polygon
2078 void FXDCWindow::fillComplexPolygon(const FXPoint* points,FXuint npoints){
2079 if(!surface){ fxerror("FXDCWindow::fillComplexPolygon: DC not connected to drawable.\n"); }
2080 XFillPolygon((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,(XPoint*)points,npoints,Complex,CoordModeOrigin);
2081 }
2082
2083
2084 // Fill polygon relative
2085 void FXDCWindow::fillPolygonRel(const FXPoint* points,FXuint npoints){
2086 if(!surface){ fxerror("FXDCWindow::fillPolygonRel: DC not connected to drawable.\n"); }
2087 XFillPolygon((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,(XPoint*)points,npoints,Convex,CoordModePrevious);
2088 }
2089
2090
2091 // Fill concave polygon relative
2092 void FXDCWindow::fillConcavePolygonRel(const FXPoint* points,FXuint npoints){
2093 if(!surface){ fxerror("FXDCWindow::fillConcavePolygonRel: DC not connected to drawable.\n"); }
2094 XFillPolygon((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,(XPoint*)points,npoints,Nonconvex,CoordModePrevious);
2095 }
2096
2097
2098 // Fill complex polygon relative
2099 void FXDCWindow::fillComplexPolygonRel(const FXPoint* points,FXuint npoints){
2100 if(!surface){ fxerror("FXDCWindow::fillComplexPolygonRel: DC not connected to drawable.\n"); }
2101 XFillPolygon((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,(XPoint*)points,npoints,Complex,CoordModePrevious);
2102 }
2103
2104
2105 // Fill vertical gradient rectangle
2106 void FXDCWindow::fillVerticalGradient(FXint x,FXint y,FXint w,FXint h,FXColor top,FXColor bottom){
2107 FXint rr,gg,bb,dr,dg,db,r1,g1,b1,r2,g2,b2,yl,yh,yy,dy,n,t;
2108 if(!surface){ fxerror("FXDCWindow::fillVerticalGradient: DC not connected to drawable.\n"); }
2109 if(0<w && 0<h){
2110 r1=FXREDVAL(top);
2111 r2=FXREDVAL(bottom);
2112 g1=FXGREENVAL(top);
2113 g2=FXGREENVAL(bottom);
2114 b1=FXBLUEVAL(top);
2115 b2=FXBLUEVAL(bottom);
2116 dr=r2-r1;
2117 dg=g2-g1;
2118 db=b2-b1;
2119 n=FXABS(dr);
2120 if((t=FXABS(dg))>n) n=t;
2121 if((t=FXABS(db))>n) n=t;
2122 n++;
2123 if(n>h) n=h;
2124 if(n>128) n=128;
2125 rr=(r1<<16)+32767;
2126 gg=(g1<<16)+32767;
2127 bb=(b1<<16)+32767;
2128 yy=32767;
2129 dr=(dr<<16)/n;
2130 dg=(dg<<16)/n;
2131 db=(db<<16)/n;
2132 dy=(h<<16)/n;
2133 do{
2134 yl=yy>>16;
2135 yy+=dy;
2136 yh=yy>>16;
2137 setForeground(FXRGB(rr>>16,gg>>16,bb>>16));
2138 fillRectangle(x,y+yl,w,yh-yl);
2139 rr+=dr;
2140 gg+=dg;
2141 bb+=db;
2142 }
2143 while(yh<h);
2144 }
2145 #if 0
2146 XLinearGradient grad;
2147 XFixed stops[2];
2148 XRenderColor colors[2];
2149
2150 grad.p1.x=0;
2151 grad.p1.y=0;
2152 grad.p2.x=0;
2153 grad.p2.y=h<<16;
2154
2155 stops[0]=0;
2156 stops[1]=1<<16;
2157
2158 colors[0].red=FXREDVAL(top)*257;
2159 colors[0].green=FXGREENVAL(top)*257;
2160 colors[0].blue=FXBLUEVAL(top)*257;
2161 colors[0].alpha=FXALPHAVAL(top)*257;
2162 colors[1].red=FXREDVAL(bottom)*257;
2163 colors[1].green=FXGREENVAL(bottom)*257;
2164 colors[1].blue=FXBLUEVAL(bottom)*257;
2165 colors[1].alpha=FXALPHAVAL(bottom)*257;
2166
2167 Picture picture=XRenderCreateLinearGradient((Display*)getApp()->getDisplay(),&grad,stops,colors,2);
2168 XRenderComposite((Display*)getApp()->getDisplay(),PictOpSrc,picture,0,surface->xrenderpicture,0,0,0,0,x,y,w,h);
2169 XRenderFreePicture((Display*)getApp()->getDisplay(),picture);
2170 #endif
2171 }
2172
2173
2174
2175 // Fill horizontal gradient rectangle
2176 void FXDCWindow::fillHorizontalGradient(FXint x,FXint y,FXint w,FXint h,FXColor left,FXColor right){
2177 FXint rr,gg,bb,dr,dg,db,r1,g1,b1,r2,g2,b2,xl,xh,xx,dx,n,t;
2178 if(!surface){ fxerror("FXDCWindow::fillHorizontalGradient: DC not connected to drawable.\n"); }
2179 if(0<w && 0<h){
2180 r1=FXREDVAL(left);
2181 r2=FXREDVAL(right);
2182 g1=FXGREENVAL(left);
2183 g2=FXGREENVAL(right);
2184 b1=FXBLUEVAL(left);
2185 b2=FXBLUEVAL(right);
2186 dr=r2-r1;
2187 dg=g2-g1;
2188 db=b2-b1;
2189 n=FXABS(dr);
2190 if((t=FXABS(dg))>n) n=t;
2191 if((t=FXABS(db))>n) n=t;
2192 n++;
2193 if(n>w) n=w;
2194 if(n>128) n=128;
2195 rr=(r1<<16)+32767;
2196 gg=(g1<<16)+32767;
2197 bb=(b1<<16)+32767;
2198 xx=32767;
2199 dr=(dr<<16)/n;
2200 dg=(dg<<16)/n;
2201 db=(db<<16)/n;
2202 dx=(w<<16)/n;
2203 do{
2204 xl=xx>>16;
2205 xx+=dx;
2206 xh=xx>>16;
2207 setForeground(FXRGB(rr>>16,gg>>16,bb>>16));
2208 fillRectangle(x+xl,y,xh-xl,h);
2209 rr+=dr;
2210 gg+=dg;
2211 bb+=db;
2212 }
2213 while(xh<w);
2214 }
2215 #if 0
2216 XLinearGradient grad;
2217 XFixed stops[2];
2218 XRenderColor colors[2];
2219
2220 grad.p1.x=0;
2221 grad.p1.y=0;
2222 grad.p2.x=w<<16;
2223 grad.p2.y=0;
2224
2225 stops[0]=0;
2226 stops[1]=1<<16;
2227
2228 colors[0].red=FXREDVAL(left)*257;
2229 colors[0].green=FXGREENVAL(left)*257;
2230 colors[0].blue=FXBLUEVAL(left)*257;
2231 colors[0].alpha=FXALPHAVAL(left)*257;
2232 colors[1].red=FXREDVAL(right)*257;
2233 colors[1].green=FXGREENVAL(right)*257;
2234 colors[1].blue=FXBLUEVAL(right)*257;
2235 colors[1].alpha=FXALPHAVAL(right)*257;
2236
2237 Picture picture=XRenderCreateLinearGradient((Display*)getApp()->getDisplay(),&grad,stops,colors,2);
2238 XRenderComposite((Display*)getApp()->getDisplay(),PictOpSrc,picture,0,surface->xrenderpicture,0,0,0,0,x,y,w,h);
2239 XRenderFreePicture((Display*)getApp()->getDisplay(),picture);
2240 #endif
2241 }
2242
2243
2244 // Set text font
2245 void FXDCWindow::setFont(FXFont *fnt){
2246 if(!surface){ fxerror("FXDCWindow::setFont: DC not connected to drawable.\n"); }
2247 if(!fnt || !fnt->id()){ fxerror("FXDCWindow::setFont: illegal or NULL font specified.\n"); }
2248 #ifndef HAVE_XFT_H
2249 XSetFont((Display*)getApp()->getDisplay(),(GC)ctx,fnt->id());
2250 flags|=GCFont;
2251 #endif
2252 font=fnt;
2253 }
2254
2255
2256 /*
2257
2258 We eventually want subclassable fonts.
2259 FXDCWindow knows about surface, but does not know about font type.
2260 Thus, drawText() here should vector to new API's in FXFont.
2261 New API gets FXDC* (or FXDC&) so that it can obtain colors, &c.
2262 Thus, all knowledge of font-technology is kept inside FXFont.
2263 Knowledge of FXDCWindow surface is kept inside FXDCWindow.
2264
2265 But FXDC may have some responsibility for layout of characters.
2266
2267 Of course, certain font types can only draw on certain DC types...
2268
2269
2270 void FXDCWindow::drawText(FXint x,FXint y,const FXchar* string,FXuint length){
2271 if(!surface){ fxerror("FXDCWindow::drawText: DC not connected to drawable.\n"); }
2272 if(!font){ fxerror("FXDCWindow::drawText: no font selected.\n"); }
2273 font->drawText(this,x,y,string,length);
2274 }
2275 */
2276
2277
2278
2279 #define FS ((XFontStruct*)(font->font))
2280
2281
2282 static FXint utf2db(XChar2b *dst,const FXchar *src,FXint n){
2283 FXint len,p;
2284 FXwchar w;
2285 for(p=len=0; p<n; p+=wclen(src+p),len++){
2286 w=wc(src+p);
2287 dst[len].byte1=(w>>8);
2288 dst[len].byte2=(w&255);
2289 }
2290 return len;
2291 }
2292
2293
2294 // Draw string with base line starting at x, y
2295 void FXDCWindow::drawText(FXint x,FXint y,const FXchar* string,FXuint length){
2296 if(!surface){ fxerror("FXDCWindow::drawText: DC not connected to drawable.\n"); }
2297 if(!font){ fxerror("FXDCWindow::drawText: no font selected.\n"); }
2298 #ifdef HAVE_XFT_H
2299 XftColor color;
2300 color.pixel=devfg;
2301 color.color.red=FXREDVAL(fg)*257;
2302 color.color.green=FXGREENVAL(fg)*257;
2303 color.color.blue=FXBLUEVAL(fg)*257;
2304 color.color.alpha=FXALPHAVAL(fg)*257;
2305 XftDrawStringUtf8((XftDraw*)xftDraw,&color,(XftFont*)font->font,x,y,(const FcChar8*)string,length);
2306 #else
2307 FXint count,escapement,defwidth,ww,size,i;
2308 FXdouble ang,ux,uy;
2309 FXuchar r,c;
2310 XChar2b sbuffer[4096];
2311 count=utf2db(sbuffer,string,FXMIN(length,4096));
2312 if(font->getAngle()){
2313 ang=font->getAngle()*0.00027270769562411399179;
2314 defwidth=FS->min_bounds.width;
2315 ux=Math::cos(ang);
2316 uy=Math::sin(ang);
2317 if(FS->per_char){
2318 r=FS->default_char>>8;
2319 c=FS->default_char&255;
2320 size=(FS->max_char_or_byte2-FS->min_char_or_byte2+1);
2321 if(FS->min_char_or_byte2<=c && c<=FS->max_char_or_byte2 && FS->min_byte1<=r && r<=FS->max_byte1){
2322 defwidth=FS->per_char[(r-FS->min_byte1)*size+(c-FS->min_char_or_byte2)].width;
2323 }
2324 for(i=escapement=0; i<count; i++){
2325 XDrawString16((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,(FXint)(x+escapement*ux),(FXint)(y-escapement*uy),&sbuffer[i],1);
2326 r=sbuffer[i].byte1;
2327 c=sbuffer[i].byte2;
2328 escapement+=defwidth;
2329 if(FS->min_char_or_byte2<=c && c<=FS->max_char_or_byte2 && FS->min_byte1<=r && r<=FS->max_byte1){
2330 if((ww=FS->per_char[(r-FS->min_byte1)*size+(c-FS->min_char_or_byte2)].width)!=0) escapement+=ww-defwidth;
2331 }
2332 }
2333 }
2334 else{
2335 for(i=escapement=0; i<count; i++){
2336 XDrawString16((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,(FXint)(x+escapement*ux),(FXint)(y-escapement*uy),&sbuffer[i],1);
2337 escapement+=defwidth;
2338 }
2339 }
2340 }
2341 else{
2342 XDrawString16((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,x,y,sbuffer,count);
2343 }
2344 #endif
2345 }
2346
2347
2348 // Draw text starting at x, y over filled background
2349 void FXDCWindow::drawImageText(FXint x,FXint y,const FXchar* string,FXuint length){
2350 if(!surface){ fxerror("FXDCWindow::drawImageText: DC not connected to drawable.\n"); }
2351 if(!font){ fxerror("FXDCWindow::drawImageText: no font selected.\n"); }
2352 #ifdef HAVE_XFT_H
2353 XGlyphInfo extents;
2354 XftColor fgcolor,bgcolor;
2355 fgcolor.pixel=devfg;
2356 fgcolor.color.red=FXREDVAL(fg)*257;
2357 fgcolor.color.green=FXGREENVAL(fg)*257;
2358 fgcolor.color.blue=FXBLUEVAL(fg)*257;
2359 fgcolor.color.alpha=FXALPHAVAL(fg)*257;
2360 bgcolor.pixel=devbg;
2361 bgcolor.color.red=FXREDVAL(bg)*257;
2362 bgcolor.color.green=FXGREENVAL(bg)*257;
2363 bgcolor.color.blue=FXBLUEVAL(bg)*257;
2364 bgcolor.color.alpha=FXALPHAVAL(bg)*257;
2365
2366 // Area to blank
2367 XftTextExtents8((Display*)getApp()->getDisplay(),(XftFont*)font->font,(const FcChar8*)string,length,&extents);
2368
2369 // Erase around text [FIXME wrong location]
2370 XftDrawRect((XftDraw*)xftDraw,&bgcolor,x,y-font->getFontAscent(),extents.width,extents.height);
2371 //XftDrawRect((XftDraw*)xftDraw,&bgcolor,x+cache->xoff,y-xftfs->ascent,cache->x2off-cache->xoff,xftfs->ascent+xftfs->descent);
2372 //XftDrawRect((XftDraw*)xftDraw,&bgcolor,x+cache->xoff,y-((XftFont*)font->font)->ascent,cache->x2off-cache->xoff,((XftFont*)font->font)->ascent+((XftFont*)font->font)->descent);
2373 XftDrawStringUtf8((XftDraw*)xftDraw,&fgcolor,(XftFont*)font->font,x,y,(const FcChar8*)string,length);
2374 #else
2375 FXint count,escapement,defwidth,ww,size,i;
2376 FXdouble ang,ux,uy;
2377 FXuchar r,c;
2378 XChar2b sbuffer[4096];
2379 count=utf2db(sbuffer,string,FXMIN(length,4096));
2380 if(font->getAngle()){
2381 ang=font->getAngle()*0.00027270769562411399179;
2382 defwidth=FS->min_bounds.width;
2383 ux=Math::cos(ang);
2384 uy=Math::sin(ang);
2385 if(FS->per_char){
2386 r=FS->default_char>>8;
2387 c=FS->default_char&255;
2388 size=(FS->max_char_or_byte2-FS->min_char_or_byte2+1);
2389 if(FS->min_char_or_byte2<=c && c<=FS->max_char_or_byte2 && FS->min_byte1<=r && r<=FS->max_byte1){
2390 defwidth=FS->per_char[(r-FS->min_byte1)*size+(c-FS->min_char_or_byte2)].width;
2391 }
2392 for(i=escapement=0; i<count; i++){
2393 XDrawString16((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,(FXint)(x+escapement*ux),(FXint)(y-escapement*uy),&sbuffer[i],1);
2394 r=sbuffer[i].byte1;
2395 c=sbuffer[i].byte2;
2396 escapement+=defwidth;
2397 if(FS->min_char_or_byte2<=c && c<=FS->max_char_or_byte2 && FS->min_byte1<=r && r<=FS->max_byte1){
2398 if((ww=FS->per_char[(r-FS->min_byte1)*size+(c-FS->min_char_or_byte2)].width)!=0) escapement+=ww-defwidth;
2399 }
2400 }
2401 }
2402 else{
2403 for(i=escapement=0; i<count; i++){
2404 XDrawImageString16((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,(FXint)(x+escapement*ux),(FXint)(y-escapement*uy),&sbuffer[i],1);
2405 escapement+=defwidth;
2406 }
2407 }
2408 }
2409 else{
2410 XDrawImageString16((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,x,y,sbuffer,count);
2411 }
2412 #endif
2413 }
2414
2415 #undef FS
2416
2417
2418
2419 // Draw string with base line starting at x, y
2420 void FXDCWindow::drawText(FXint x,FXint y,const FXString& string){
2421 drawText(x,y,string.text(),string.length());
2422 }
2423
2424
2425 // Draw text starting at x, y over filled background
2426 void FXDCWindow::drawImageText(FXint x,FXint y,const FXString& string){
2427 drawImageText(x,y,string.text(),string.length());
2428 }
2429
2430
2431 // Draw area
2432 void FXDCWindow::drawArea(const FXDrawable* source,FXint sx,FXint sy,FXint sw,FXint sh,FXint dx,FXint dy){
2433 if(!surface){ fxerror("FXDCWindow::drawArea: DC not connected to drawable.\n"); }
2434 if(!source || !source->id()){ fxerror("FXDCWindow::drawArea: illegal source specified.\n"); }
2435 XCopyArea((Display*)getApp()->getDisplay(),source->id(),surface->id(),(GC)ctx,sx,sy,sw,sh,dx,dy);
2436 }
2437
2438
2439 // Draw area stretched area from source; FIXME this works but it's like molasses!
2440 void FXDCWindow::drawArea(const FXDrawable* source,FXint sx,FXint sy,FXint sw,FXint sh,FXint dx,FXint dy,FXint dw,FXint dh){
2441 FXint i,j,x,y,xs,ys;
2442 if(!surface){ fxerror("FXDCWindow::drawArea: DC not connected to drawable.\n"); }
2443 if(!source || !source->id()){ fxerror("FXDCWindow::drawArea: illegal source specified.\n"); }
2444 xs=(sw<<16)/dw;
2445 ys=(sh<<16)/dh;
2446 i=0;
2447 y=ys>>1;
2448 do{
2449 j=0;
2450 x=xs>>1;
2451 do{
2452 XCopyArea((Display*)getApp()->getDisplay(),source->id(),surface->id(),(GC)ctx,sx+(x>>16),sy+(y>>16),1,1,dx+j,dy+i);
2453 x+=xs;
2454 }
2455 while(++j<dw);
2456 y+=ys;
2457 }
2458 while(++i<dh);
2459 }
2460
2461
2462 // Draw image
2463 void FXDCWindow::drawImage(const FXImage* image,FXint dx,FXint dy){
2464 if(!surface){ fxerror("FXDCWindow::drawImage: DC not connected to drawable.\n"); }
2465 if(!image || !image->id()){ fxerror("FXDCWindow::drawImage: illegal image specified.\n"); }
2466 XCopyArea((Display*)getApp()->getDisplay(),image->id(),surface->id(),(GC)ctx,0,0,image->width,image->height,dx,dy);
2467 }
2468
2469
2470 // Draw bitmap
2471 void FXDCWindow::drawBitmap(const FXBitmap* bitmap,FXint dx,FXint dy) {
2472 if(!surface) fxerror("FXDCWindow::drawBitmap: DC not connected to drawable.\n");
2473 if(!bitmap || !bitmap->id()) fxerror("FXDCWindow::drawBitmap: illegal bitmap specified.\n");
2474 XCopyPlane((Display*)getApp()->getDisplay(),bitmap->id(),surface->id(),(GC)ctx,0,0,bitmap->width,bitmap->height,dx,dy,1);
2475 }
2476
2477
2478 // Draw a vanilla icon
2479 void FXDCWindow::drawIcon(const FXIcon* icon,FXint dx,FXint dy){
2480 if(!surface){ fxerror("FXDCWindow::drawIcon: DC not connected to drawable.\n"); }
2481 if(!icon || !icon->id() || !icon->shape){ fxerror("FXDCWindow::drawIcon: illegal icon specified.\n"); }
2482 FXRectangle d=clip*FXRectangle(dx,dy,icon->width,icon->height);
2483 if(d.w>0 && d.h>0){
2484 if(icon->getOptions()&IMAGE_OPAQUE){
2485 XCopyArea((Display*)getApp()->getDisplay(),icon->id(),surface->id(),(GC)ctx,d.x-dx,d.y-dy,d.w,d.h,d.x,d.y);
2486 }
2487 else{
2488 XGCValues gcv;
2489 gcv.clip_mask=icon->shape;
2490 gcv.clip_x_origin=dx;
2491 gcv.clip_y_origin=dy;
2492 XChangeGC((Display*)getApp()->getDisplay(),(GC)ctx,GCClipMask|GCClipXOrigin|GCClipYOrigin,&gcv);
2493 XCopyArea((Display*)getApp()->getDisplay(),icon->id(),surface->id(),(GC)ctx,d.x-dx,d.y-dy,d.w,d.h,d.x,d.y);
2494 XSetClipRectangles((Display*)getApp()->getDisplay(),(GC)ctx,0,0,(XRectangle*)(void*)&clip,1,Unsorted); // Restore old clip rectangle
2495 flags|=GCClipMask;
2496 }
2497 }
2498 }
2499
2500
2501 // Draw a shaded icon, like when it is selected
2502 void FXDCWindow::drawIconShaded(const FXIcon* icon,FXint dx,FXint dy){
2503 if(!surface){ fxerror("FXDCWindow::drawIconShaded: DC not connected to drawable.\n"); }
2504 if(!icon || !icon->id() || !icon->shape){ fxerror("FXDCWindow::drawIconShaded: illegal icon specified.\n"); }
2505 FXRectangle d=clip*FXRectangle(dx,dy,icon->width,icon->height);
2506 if(d.w>0 && d.h>0){
2507 XGCValues gcv;
2508 gcv.clip_mask=icon->shape;
2509 gcv.clip_x_origin=dx;
2510 gcv.clip_y_origin=dy;
2511 XChangeGC((Display*)getApp()->getDisplay(),(GC)ctx,GCClipMask|GCClipXOrigin|GCClipYOrigin,&gcv);
2512 XCopyArea((Display*)getApp()->getDisplay(),icon->id(),surface->id(),(GC)ctx,d.x-dx,d.y-dy,d.w,d.h,d.x,d.y);
2513 gcv.function=BLT_SRC;
2514 gcv.stipple=getApp()->stipples[STIPPLE_GRAY];
2515 gcv.fill_style=FILL_STIPPLED;
2516 gcv.ts_x_origin=dx;
2517 gcv.ts_y_origin=dy;
2518 gcv.foreground=surface->visual->getPixel(getApp()->getSelbackColor());
2519 XChangeGC((Display*)getApp()->getDisplay(),(GC)ctx,GCForeground|GCFunction|GCTileStipXOrigin|GCTileStipYOrigin|GCStipple|GCFillStyle,&gcv);
2520 XFillRectangle((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,d.x,d.y,d.w,d.h);
2521 gcv.function=rop;
2522 gcv.fill_style=fill;
2523 gcv.ts_x_origin=tx;
2524 gcv.ts_y_origin=ty;
2525 XChangeGC((Display*)getApp()->getDisplay(),(GC)ctx,GCTileStipXOrigin|GCTileStipYOrigin|GCFunction|GCFillStyle,&gcv); // Restore old raster op function and fill style
2526 XSetClipRectangles((Display*)getApp()->getDisplay(),(GC)ctx,0,0,(XRectangle*)(void*)&clip,1,Unsorted); // Restore old clip rectangle
2527 flags|=GCClipMask;
2528 }
2529 }
2530
2531
2532 // This draws a sunken icon
2533 void FXDCWindow::drawIconSunken(const FXIcon* icon,FXint dx,FXint dy){
2534 if(!surface){ fxerror("FXDCWindow::drawIconSunken: DC not connected to drawable.\n"); }
2535 if(!icon || !icon->id() || !icon->etch){ fxerror("FXDCWindow::drawIconSunken: illegal icon specified.\n"); }
2536 XGCValues gcv;
2537 FXColor base=getApp()->getBaseColor();
2538 FXColor clr=FXRGB((85*FXREDVAL(base))/100,(85*FXGREENVAL(base))/100,(85*FXBLUEVAL(base))/100);
2539
2540 // Erase to black
2541 gcv.background=0;
2542 gcv.foreground=0xffffffff;
2543 gcv.function=BLT_NOT_SRC_AND_DST;
2544 XChangeGC((Display*)getApp()->getDisplay(),(GC)ctx,GCForeground|GCBackground|GCFunction,&gcv);
2545 XCopyPlane((Display*)getApp()->getDisplay(),icon->etch,surface->id(),(GC)ctx,0,0,icon->width,icon->height,dx+1,dy+1,1);
2546
2547 // Paint highlight part
2548 gcv.function=BLT_SRC_OR_DST;
2549 gcv.foreground=surface->visual->getPixel(getApp()->getHiliteColor());
2550 XChangeGC((Display*)getApp()->getDisplay(),(GC)ctx,GCForeground|GCFunction,&gcv);
2551 XCopyPlane((Display*)getApp()->getDisplay(),icon->etch,surface->id(),(GC)ctx,0,0,icon->width,icon->height,dx+1,dy+1,1);
2552
2553 // Erase to black
2554 gcv.foreground=0xffffffff;
2555 gcv.function=BLT_NOT_SRC_AND_DST;
2556 XChangeGC((Display*)getApp()->getDisplay(),(GC)ctx,GCForeground|GCFunction,&gcv);
2557 XCopyPlane((Display*)getApp()->getDisplay(),icon->etch,surface->id(),(GC)ctx,0,0,icon->width,icon->height,dx,dy,1);
2558
2559 // Paint shadow part
2560 gcv.function=BLT_SRC_OR_DST;
2561 gcv.foreground=surface->visual->getPixel(clr);
2562 XChangeGC((Display*)getApp()->getDisplay(),(GC)ctx,GCForeground|GCFunction,&gcv);
2563 XCopyPlane((Display*)getApp()->getDisplay(),icon->etch,surface->id(),(GC)ctx,0,0,icon->width,icon->height,dx,dy,1);
2564
2565 // Restore stuff
2566 gcv.foreground=devfg;
2567 gcv.background=devbg;
2568 gcv.function=rop;
2569 XChangeGC((Display*)getApp()->getDisplay(),(GC)ctx,GCForeground|GCBackground|GCFunction,&gcv);
2570 }
2571
2572
2573 // Draw hash box
2574 void FXDCWindow::drawHashBox(FXint x,FXint y,FXint w,FXint h,FXint b){
2575 XGCValues gcv;
2576 if(!surface){ fxerror("FXDCWindow::drawHashBox: DC not connected to drawable.\n"); }
2577 gcv.stipple=getApp()->stipples[STIPPLE_GRAY];
2578 gcv.fill_style=FILL_STIPPLED;
2579 XChangeGC((Display*)getApp()->getDisplay(),(GC)ctx,GCStipple|GCFillStyle,&gcv);
2580 XFillRectangle((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,x,y,w-b,b);
2581 XFillRectangle((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,x+w-b,y,b,h-b);
2582 XFillRectangle((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,x+b,y+h-b,w-b,b);
2583 XFillRectangle((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,x,y+b,b,h-b);
2584 gcv.stipple=getApp()->stipples[STIPPLE_WHITE]; // Needed for IRIX6.4 bug workaround!
2585 gcv.fill_style=fill;
2586 XChangeGC((Display*)getApp()->getDisplay(),(GC)ctx,GCStipple|GCFillStyle,&gcv);
2587 }
2588
2589
2590 // Draw focus rectangle
2591 void FXDCWindow::drawFocusRectangle(FXint x,FXint y,FXint w,FXint h){
2592 XGCValues gcv;
2593 if(!surface){ fxerror("FXDCWindow::drawFocusRectangle: DC not connected to drawable.\n"); }
2594 gcv.stipple=getApp()->stipples[STIPPLE_GRAY];
2595 gcv.fill_style=FILL_STIPPLED;
2596 gcv.background=0;
2597 gcv.foreground=0xffffffff; // Maybe should use FILL_OPAQUESTIPPLED and current fg/bg color and BLT_SRC
2598 gcv.function=BLT_SRC_XOR_DST; // This would be more flexible
2599 gcv.ts_x_origin=x;
2600 gcv.ts_y_origin=y;
2601 XChangeGC((Display*)getApp()->getDisplay(),(GC)ctx,GCTileStipXOrigin|GCTileStipYOrigin|GCForeground|GCBackground|GCFunction|GCStipple|GCFillStyle,&gcv);
2602 XFillRectangle((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,x,y,w-1,1);
2603 XFillRectangle((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,x+w-1,y,1,h-1);
2604 XFillRectangle((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,x+1,y+h-1,w-1,1);
2605 XFillRectangle((Display*)getApp()->getDisplay(),surface->id(),(GC)ctx,x,y+1,1,h-1);
2606 gcv.stipple=getApp()->stipples[STIPPLE_WHITE]; // Needed for IRIX6.4 bug workaround!
2607 gcv.fill_style=fill;
2608 gcv.background=devbg;
2609 gcv.foreground=devfg;
2610 gcv.function=rop;
2611 gcv.ts_x_origin=tx;
2612 gcv.ts_y_origin=ty;
2613 XChangeGC((Display*)getApp()->getDisplay(),(GC)ctx,GCTileStipXOrigin|GCTileStipYOrigin|GCForeground|GCBackground|GCFunction|GCStipple|GCFillStyle,&gcv);
2614 }
2615
2616
2617 // Set foreground color
2618 void FXDCWindow::setForeground(FXColor clr){
2619 if(!surface){ fxerror("FXDCWindow::setForeground: DC not connected to drawable.\n"); }
2620 devfg=surface->visual->getPixel(clr);
2621 XSetForeground((Display*)getApp()->getDisplay(),(GC)ctx,devfg);
2622 flags|=GCForeground;
2623 fg=clr;
2624 }
2625
2626
2627 // Set background color
2628 void FXDCWindow::setBackground(FXColor clr){
2629 if(!surface){ fxerror("FXDCWindow::setBackground: DC not connected to drawable.\n"); }
2630 devbg=surface->visual->getPixel(clr);
2631 XSetBackground((Display*)getApp()->getDisplay(),(GC)ctx,devbg);
2632 flags|=GCBackground;
2633 bg=clr;
2634 }
2635
2636
2637 // Set dashes
2638 void FXDCWindow::setDashes(FXuint dashoffset,const FXchar *dashpattern,FXuint dashlength){
2639 FXuint len,i;
2640 if(!surface){ fxerror("FXDCWindow::setDashes: DC not connected to drawable.\n"); }
2641 if(dashlength>32){ fxerror("FXDCWindow::setDashes: bad dashlength parameter.\n"); }
2642 for(i=len=0; i<dashlength; i++){
2643 dashpat[i]=dashpattern[i];
2644 len+=(FXuint)dashpattern[i];
2645 }
2646 dashlen=dashlength;
2647 dashoff=dashoffset%len;
2648 XSetDashes((Display*)getApp()->getDisplay(),(GC)ctx,dashoff,(char*)dashpat,dashlen);
2649 flags|=(GCDashList|GCDashOffset);
2650 }
2651
2652
2653 // Set line width
2654 void FXDCWindow::setLineWidth(FXuint linewidth){
2655 XGCValues gcv;
2656 if(!surface){ fxerror("FXDCWindow::setLineWidth: DC not connected to drawable.\n"); }
2657 gcv.line_width=linewidth;
2658 XChangeGC((Display*)getApp()->getDisplay(),(GC)ctx,GCLineWidth,&gcv);
2659 flags|=GCLineWidth;
2660 width=linewidth;
2661 }
2662
2663
2664 // Set line cap style
2665 void FXDCWindow::setLineCap(FXCapStyle capstyle){
2666 XGCValues gcv;
2667 if(!surface){ fxerror("FXDCWindow::setLineCap: DC not connected to drawable.\n"); }
2668 gcv.cap_style=capstyle;
2669 XChangeGC((Display*)getApp()->getDisplay(),(GC)ctx,GCCapStyle,&gcv);
2670 flags|=GCCapStyle;
2671 cap=capstyle;
2672 }
2673
2674
2675 // Set line join style
2676 void FXDCWindow::setLineJoin(FXJoinStyle joinstyle){
2677 XGCValues gcv;
2678 if(!surface){ fxerror("FXDCWindow::setLineJoin: DC not connected to drawable.\n"); }
2679 gcv.join_style=joinstyle;
2680 XChangeGC((Display*)getApp()->getDisplay(),(GC)ctx,GCJoinStyle,&gcv);
2681 flags|=GCJoinStyle;
2682 join=joinstyle;
2683 }
2684
2685
2686 // Set line style
2687 void FXDCWindow::setLineStyle(FXLineStyle linestyle){
2688 XGCValues gcv;
2689 if(!surface){ fxerror("FXDCWindow::setLineStyle: DC not connected to drawable.\n"); }
2690 gcv.line_style=linestyle;
2691 XChangeGC((Display*)getApp()->getDisplay(),(GC)ctx,GCLineStyle,&gcv);
2692 flags|=GCLineStyle;
2693 style=linestyle;
2694 }
2695
2696
2697 // Set fill style
2698 void FXDCWindow::setFillStyle(FXFillStyle fillstyle){
2699 if(!surface){ fxerror("FXDCWindow::setFillStyle: DC not connected to drawable.\n"); }
2700 XSetFillStyle((Display*)getApp()->getDisplay(),(GC)ctx,fillstyle);
2701 flags|=GCFillStyle;
2702 fill=fillstyle;
2703 }
2704
2705
2706 // Set polygon fill rule
2707 void FXDCWindow::setFillRule(FXFillRule fillrule){
2708 if(!surface){ fxerror("FXDCWindow::setFillRule: DC not connected to drawable.\n"); }
2709 XSetFillRule((Display*)getApp()->getDisplay(),(GC)ctx,fillrule);
2710 flags|=GCFillRule;
2711 rule=fillrule;
2712 }
2713
2714
2715 // Set raster function
2716 void FXDCWindow::setFunction(FXFunction func){
2717 if(!surface){ fxerror("FXDCWindow::setFunction: DC not connected to drawable.\n"); }
2718 XSetFunction((Display*)getApp()->getDisplay(),(GC)ctx,func);
2719 flags|=GCFunction;
2720 rop=func;
2721 }
2722
2723
2724 // Set tile pattern
2725 void FXDCWindow::setTile(FXImage* image,FXint dx,FXint dy){
2726 XGCValues gcv;
2727 if(!surface){ fxerror("FXDCWindow::setTile: DC not connected to drawable.\n"); }
2728 if(!image || !image->id()){ fxerror("FXDCWindow::setTile: illegal image specified.\n"); }
2729 gcv.tile=image->id();
2730 gcv.ts_x_origin=dx;
2731 gcv.ts_y_origin=dy;
2732 XChangeGC((Display*)getApp()->getDisplay(),(GC)ctx,GCTileStipXOrigin|GCTileStipYOrigin|GCTile,&gcv);
2733 if(dx) flags|=GCTileStipXOrigin;
2734 if(dy) flags|=GCTileStipYOrigin;
2735 tile=image;
2736 tx=dx;
2737 ty=dy;
2738 }
2739
2740
2741 // Set stipple bitmap
2742 void FXDCWindow::setStipple(FXBitmap* bitmap,FXint dx,FXint dy){
2743 XGCValues gcv;
2744 if(!surface){ fxerror("FXDCWindow::setStipple: DC not connected to drawable.\n"); }
2745 if(!bitmap || !bitmap->id()){ fxerror("FXDCWindow::setStipple: illegal image specified.\n"); }
2746 gcv.stipple=bitmap->id();
2747 gcv.ts_x_origin=dx;
2748 gcv.ts_y_origin=dy;
2749 XChangeGC((Display*)getApp()->getDisplay(),(GC)ctx,GCTileStipXOrigin|GCTileStipYOrigin|GCStipple,&gcv);
2750 if(dx) flags|=GCTileStipXOrigin;
2751 if(dy) flags|=GCTileStipYOrigin;
2752 flags|=GCStipple;
2753 stipple=bitmap;
2754 pattern=STIPPLE_NONE;
2755 tx=dx;
2756 ty=dy;
2757 }
2758
2759
2760 // Set stipple pattern
2761 void FXDCWindow::setStipple(FXStipplePattern pat,FXint dx,FXint dy){
2762 XGCValues gcv;
2763 if(!surface){ fxerror("FXDCWindow::setStipple: DC not connected to drawable.\n"); }
2764 if(pat>STIPPLE_CROSSDIAG) pat=STIPPLE_CROSSDIAG;
2765 FXASSERT(getApp()->stipples[pat]);
2766 gcv.stipple=getApp()->stipples[pat];
2767 gcv.ts_x_origin=dx;
2768 gcv.ts_y_origin=dy;
2769 XChangeGC((Display*)getApp()->getDisplay(),(GC)ctx,GCTileStipXOrigin|GCTileStipYOrigin|GCStipple,&gcv);
2770 if(dx) flags|=GCTileStipXOrigin;
2771 if(dy) flags|=GCTileStipYOrigin;
2772 stipple=NULL;
2773 pattern=pat;
2774 flags|=GCStipple;
2775 tx=dx;
2776 ty=dy;
2777 }
2778
2779
2780 // Set clip region
2781 void FXDCWindow::setClipRegion(const FXRegion& region){
2782 if(!surface){ fxerror("FXDCWindow::setClipRegion: DC not connected to drawable.\n"); }
2783 XSetRegion((Display*)getApp()->getDisplay(),(GC)ctx,(Region)region.region);///// Should intersect region and rect??
2784 #ifdef HAVE_XFT_H
2785 XftDrawSetClip((XftDraw*)xftDraw,(Region)region.region);
2786 #endif
2787 flags|=GCClipMask;
2788 }
2789
2790
2791 // Set clip rectangle
2792 void FXDCWindow::setClipRectangle(FXint x,FXint y,FXint w,FXint h){
2793 if(!surface){ fxerror("FXDCWindow::setClipRectangle: DC not connected to drawable.\n"); }
2794 clip.x=FXMAX(x,rect.x);
2795 clip.y=FXMAX(y,rect.y);
2796 clip.w=FXMIN(x+w,rect.x+rect.w)-clip.x;
2797 clip.h=FXMIN(y+h,rect.y+rect.h)-clip.y;
2798 if(clip.w<=0) clip.w=0;
2799 if(clip.h<=0) clip.h=0;
2800 XSetClipRectangles((Display*)getApp()->getDisplay(),(GC)ctx,0,0,(XRectangle*)(void*)&clip,1,Unsorted);
2801 #ifdef HAVE_XFT_H
2802 XftDrawSetClipRectangles((XftDraw*)xftDraw,0,0,(XRectangle*)(void*)&clip,1);
2803 #endif
2804 flags|=GCClipMask;
2805 }
2806
2807
2808 // Set clip rectangle
2809 void FXDCWindow::setClipRectangle(const FXRectangle& rectangle){
2810 if(!surface){ fxerror("FXDCWindow::setClipRectangle: DC not connected to drawable.\n"); }
2811 clip.x=FXMAX(rectangle.x,rect.x);
2812 clip.y=FXMAX(rectangle.y,rect.y);
2813 clip.w=FXMIN(rectangle.x+rectangle.w,rect.x+rect.w)-clip.x;
2814 clip.h=FXMIN(rectangle.y+rectangle.h,rect.y+rect.h)-clip.y;
2815 if(clip.w<=0) clip.w=0;
2816 if(clip.h<=0) clip.h=0;
2817 XSetClipRectangles((Display*)getApp()->getDisplay(),(GC)ctx,0,0,(XRectangle*)(void*)&clip,1,Unsorted);
2818 #ifdef HAVE_XFT_H
2819 XftDrawSetClipRectangles((XftDraw*)xftDraw,0,0,(XRectangle*)(void*)&clip,1);
2820 #endif
2821 flags|=GCClipMask;
2822 }
2823
2824
2825 // Clear clip rectangle
2826 void FXDCWindow::clearClipRectangle(){
2827 if(!surface){ fxerror("FXDCWindow::clearClipRectangle: DC not connected to drawable.\n"); }
2828 clip=rect;
2829 XSetClipRectangles((Display*)getApp()->getDisplay(),(GC)ctx,0,0,(XRectangle*)(void*)&clip,1,Unsorted);
2830 #ifdef HAVE_XFT_H
2831 XftDrawSetClipRectangles((XftDraw*)xftDraw,0,0,(XRectangle*)(void*)&clip,1);
2832 #endif
2833 flags|=GCClipMask;
2834 }
2835
2836
2837 // Set clip mask
2838 void FXDCWindow::setClipMask(FXBitmap* bitmap,FXint dx,FXint dy){
2839 XGCValues gcv;
2840 if(!surface){ fxerror("FXDCWindow::setClipMask: DC not connected to drawable.\n"); }
2841 if(!bitmap || !bitmap->id()){ fxerror("FXDCWindow::setClipMask: illegal mask specified.\n"); }
2842 gcv.clip_mask=bitmap->id();
2843 gcv.clip_x_origin=dx;
2844 gcv.clip_y_origin=dy;
2845 XChangeGC((Display*)getApp()->getDisplay(),(GC)ctx,GCClipMask|GCClipXOrigin|GCClipYOrigin,&gcv);
2846 if(dx) flags|=GCClipXOrigin;
2847 if(dy) flags|=GCClipYOrigin;
2848 flags|=GCClipMask;
2849 mask=bitmap;
2850 cx=dx;
2851 cy=dy;
2852 }
2853
2854
2855 // Clear clip mask
2856 void FXDCWindow::clearClipMask(){
2857 if(!surface){ fxerror("FXDCWindow::clearClipMask: DC not connected to drawable.\n"); }
2858 clip=rect;
2859 XSetClipRectangles((Display*)getApp()->getDisplay(),(GC)ctx,0,0,(XRectangle*)(void*)&clip,1,Unsorted);
2860 flags|=GCClipMask;
2861 mask=NULL;
2862 cx=0;
2863 cy=0;
2864 }
2865
2866
2867 // Set clip child windows
2868 void FXDCWindow::clipChildren(FXbool yes){
2869 if(!surface){ fxerror("FXDCWindow::clipChildren: window has not yet been created.\n"); }
2870 if(yes){
2871 XSetSubwindowMode((Display*)getApp()->getDisplay(),(GC)ctx,ClipByChildren);
2872 #ifdef HAVE_XFT_H
2873 XftDrawSetSubwindowMode((XftDraw*)xftDraw,ClipByChildren);
2874 #endif
2875 flags&=~GCSubwindowMode;
2876 }
2877 else{
2878 XSetSubwindowMode((Display*)getApp()->getDisplay(),(GC)ctx,IncludeInferiors);
2879 #ifdef HAVE_XFT_H
2880 XftDrawSetSubwindowMode((XftDraw*)xftDraw,IncludeInferiors);
2881 #endif
2882 flags|=GCSubwindowMode;
2883 }
2884 }
2885
2886
2887 #endif
2888
2889 }
2890