~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/gdi32/enhmfdrv/graphics.c

Version: ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~ [ wine-1.0-rc5 ] ~ [ wine-1.0-rc4 ] ~ [ wine-1.0-rc3 ] ~ [ wine-1.0-rc2 ] ~ [ wine-1.0-rc1 ] ~ [ wine-0.9.61 ] ~ [ wine-0.9.60 ] ~ [ wine-0.9.59 ] ~ [ wine-0.9.58 ] ~ [ wine-0.9.57 ] ~ [ wine-0.9.56 ] ~ [ wine-0.9.55 ] ~ [ wine-0.9.54 ] ~ [ wine-0.9.53 ] ~ [ wine-0.9.52 ] ~ [ wine-0.9.51 ] ~ [ wine-0.9.50 ] ~ [ wine-0.9.49 ] ~ [ wine-0.9.48 ] ~ [ wine-0.9.47 ] ~ [ wine-0.9.46 ] ~ [ wine-0.9.45 ] ~ [ wine-0.9.44 ] ~ [ wine-0.9.43 ] ~ [ wine-0.9.42 ] ~ [ wine-0.9.41 ] ~ [ wine-0.9.40 ] ~ [ wine-0.9.39 ] ~ [ wine-0.9.38 ] ~ [ wine-0.9.37 ] ~ [ wine-0.9.36 ] ~ [ wine-0.9.35 ] ~ [ wine-0.9.34 ] ~ [ wine-0.9.33 ] ~ [ wine-0.9.32 ] ~ [ wine-0.9.31 ] ~ [ wine-0.9.30 ] ~ [ wine-0.9.29 ] ~ [ wine-0.9.28 ] ~ [ wine-0.9.27 ] ~ [ wine-0.9.26 ] ~ [ wine-0.9.25 ] ~ [ wine-0.9.24 ] ~ [ wine-0.9.23 ] ~ [ wine-0.9.22 ] ~ [ wine-0.9.21 ] ~ [ wine-0.9.20 ] ~ [ wine-0.9.19 ] ~ [ wine-0.9.18 ] ~ [ wine-0.9.17 ] ~ [ wine-0.9.16 ] ~ [ wine-0.9.15 ] ~ [ wine-0.9.14 ] ~ [ wine-0.9.13 ] ~ [ wine-0.9.12 ] ~ [ wine-0.9.11 ] ~ [ wine-0.9.10 ] ~ [ wine-0.9.9 ] ~ [ wine-0.9.8 ] ~ [ wine-0.9.7 ] ~ [ wine-0.9.6 ] ~ [ wine-0.9.5 ] ~ [ wine-0.9.4 ] ~ [ wine-0.9.3 ] ~ [ wine-0.9.2 ] ~ [ wine-0.9.1 ] ~ [ wine-0.9 ] ~ [ wine20050930 ] ~ [ wine20050830 ] ~ [ wine20050725 ] ~ [ wine20050628 ] ~ [ wine20050524 ] ~ [ wine20050419 ] ~ [ wine20050310 ] ~ [ wine20050211 ] ~ [ wine20050111 ] ~ [ wine20041201 ] ~ [ wine20041019 ] ~ [ wine20040914 ] ~ [ wine20040813 ] ~ [ wine20040716 ] ~ [ wine20040615 ] ~ [ wine20040505 ] ~ [ wine20040408 ] ~ [ wine20040309 ] ~ [ wine20040213 ] ~ [ wine20040121 ] ~ [ wine20031212 ] ~ [ wine20031118 ] ~ [ wine20031016 ] ~ [ wine20030911 ] ~ [ wine20030813 ] ~ [ wine20030709 ] ~ [ wine20030618 ] ~ [ wine20030508 ] ~ [ wine20030408 ] ~ [ wine20030318 ] ~ [ wine20030219 ] ~ [ wine20030115 ] ~ [ wine20021219 ] ~ [ wine20021125 ] ~ [ wine20021031 ] ~ [ wine20021007 ] ~ [ wine20020904 ] ~ [ wine20020804 ] ~ [ wine20020710 ] ~ [ wine20020605 ] ~ [ wine20020509 ] ~ [ wine20020411 ] ~ [ wine20020310 ] ~ [ wine20020228 ] ~ [ wine20011226 ] ~ [ wine20011108 ] ~ [ wine20011004 ] ~ [ wine20010824 ] ~ [ wine20010731 ] ~ [ wine20010629 ] ~ [ wine20010510 ] ~ [ wine20010418 ] ~ [ wine20010326 ] ~ [ wine20010305 ] ~ [ wine20010216 ] ~ [ wine20010112 ] ~ [ wine20001222 ] ~ [ wine20001202 ] ~ [ wine20001026 ] ~ [ wine20001002 ] ~ [ wine20000909 ] ~ [ wine20000821 ] ~ [ wine20000801 ] ~ [ wine20000716 ] ~ [ wine20000326 ] ~ [ wine20000227 ] ~ [ wine20000130 ] ~ [ wine20000109 ] ~

  1 /*
  2  * Enhanced MetaFile driver graphics functions
  3  *
  4  * Copyright 1999 Huw D M Davies
  5  *
  6  * This library is free software; you can redistribute it and/or
  7  * modify it under the terms of the GNU Lesser General Public
  8  * License as published by the Free Software Foundation; either
  9  * version 2.1 of the License, or (at your option) any later version.
 10  *
 11  * This library is distributed in the hope that it will be useful,
 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 14  * Lesser General Public License for more details.
 15  *
 16  * You should have received a copy of the GNU Lesser General Public
 17  * License along with this library; if not, write to the Free Software
 18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 19  */
 20 
 21 #include "config.h"
 22 #include "wine/port.h"
 23 
 24 #include <stdarg.h>
 25 #include <stdlib.h>
 26 #include <string.h>
 27 
 28 #include "windef.h"
 29 #include "winbase.h"
 30 #include "wingdi.h"
 31 #include "enhmfdrv/enhmetafiledrv.h"
 32 #include "wine/debug.h"
 33 
 34 WINE_DEFAULT_DEBUG_CHANNEL(enhmetafile);
 35 
 36 /**********************************************************************
 37  *           EMFDRV_MoveTo
 38  */
 39 BOOL
 40 EMFDRV_MoveTo(PHYSDEV dev, INT x, INT y)
 41 {
 42     EMRMOVETOEX emr;
 43 
 44     emr.emr.iType = EMR_MOVETOEX;
 45     emr.emr.nSize = sizeof(emr);
 46     emr.ptl.x = x;
 47     emr.ptl.y = y;
 48 
 49     return EMFDRV_WriteRecord( dev, &emr.emr );
 50 }
 51 
 52 /***********************************************************************
 53  *           EMFDRV_LineTo
 54  */
 55 BOOL
 56 EMFDRV_LineTo( PHYSDEV dev, INT x, INT y )
 57 {
 58     POINT pt;
 59     EMRLINETO emr;
 60     RECTL bounds;
 61     EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev;
 62 
 63     emr.emr.iType = EMR_LINETO;
 64     emr.emr.nSize = sizeof(emr);
 65     emr.ptl.x = x;
 66     emr.ptl.y = y;
 67 
 68     if(!EMFDRV_WriteRecord( dev, &emr.emr ))
 69         return FALSE;
 70 
 71     GetCurrentPositionEx(physDev->hdc, &pt);
 72 
 73     bounds.left   = min(x, pt.x);
 74     bounds.top    = min(y, pt.y);
 75     bounds.right  = max(x, pt.x);
 76     bounds.bottom = max(y, pt.y);
 77 
 78     EMFDRV_UpdateBBox( dev, &bounds );
 79 
 80     return TRUE;
 81 }
 82 
 83 
 84 /***********************************************************************
 85  *           EMFDRV_ArcChordPie
 86  */
 87 static BOOL
 88 EMFDRV_ArcChordPie( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
 89                     INT xstart, INT ystart, INT xend, INT yend, DWORD iType )
 90 {
 91     INT temp, xCentre, yCentre, i;
 92     double angleStart, angleEnd;
 93     double xinterStart, yinterStart, xinterEnd, yinterEnd;
 94     EMRARC emr;
 95     RECTL bounds;
 96     EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev;
 97 
 98     if(left == right || top == bottom) return FALSE;
 99 
100     if(left > right) {temp = left; left = right; right = temp;}
101     if(top > bottom) {temp = top; top = bottom; bottom = temp;}
102 
103     if(GetGraphicsMode(physDev->hdc) == GM_COMPATIBLE) {
104         right--;
105         bottom--;
106     }
107 
108     emr.emr.iType     = iType;
109     emr.emr.nSize     = sizeof(emr);
110     emr.rclBox.left   = left;
111     emr.rclBox.top    = top;
112     emr.rclBox.right  = right;
113     emr.rclBox.bottom = bottom;
114     emr.ptlStart.x    = xstart;
115     emr.ptlStart.y    = ystart;
116     emr.ptlEnd.x      = xend;
117     emr.ptlEnd.x      = yend;
118 
119 
120     /* Now calculate the BBox */
121     xCentre = (left + right + 1) / 2;
122     yCentre = (top + bottom + 1) / 2;
123 
124     xstart -= xCentre;
125     ystart -= yCentre;
126     xend   -= xCentre;
127     yend   -= yCentre;
128 
129     /* invert y co-ords to get angle anti-clockwise from x-axis */
130     angleStart = atan2( -(double)ystart, (double)xstart);
131     angleEnd   = atan2( -(double)yend, (double)xend);
132 
133     /* These are the intercepts of the start/end lines with the arc */
134 
135     xinterStart = (right - left + 1)/2 * cos(angleStart) + xCentre;
136     yinterStart = -(bottom - top + 1)/2 * sin(angleStart) + yCentre;
137     xinterEnd   = (right - left + 1)/2 * cos(angleEnd) + xCentre;
138     yinterEnd   = -(bottom - top + 1)/2 * sin(angleEnd) + yCentre;
139 
140     if(angleStart < 0) angleStart += 2 * M_PI;
141     if(angleEnd < 0) angleEnd += 2 * M_PI;
142     if(angleEnd < angleStart) angleEnd += 2 * M_PI;
143 
144     bounds.left   = min(xinterStart, xinterEnd);
145     bounds.top    = min(yinterStart, yinterEnd);
146     bounds.right  = max(xinterStart, xinterEnd);
147     bounds.bottom = max(yinterStart, yinterEnd);
148 
149     for(i = 0; i <= 8; i++) {
150         if(i * M_PI / 2 < angleStart) /* loop until we're past start */
151             continue;
152         if(i * M_PI / 2 > angleEnd)   /* if we're past end we're finished */
153             break;
154 
155         /* the arc touches the rectangle at the start of quadrant i, so adjust
156            BBox to reflect this. */
157 
158         switch(i % 4) {
159         case 0:
160             bounds.right = right;
161             break;
162         case 1:
163             bounds.top = top;
164             break;
165         case 2:
166             bounds.left = left;
167             break;
168         case 3:
169             bounds.bottom = bottom;
170             break;
171         }
172     }
173 
174     /* If we're drawing a pie then make sure we include the centre */
175     if(iType == EMR_PIE) {
176         if(bounds.left > xCentre) bounds.left = xCentre;
177         else if(bounds.right < xCentre) bounds.right = xCentre;
178         if(bounds.top > yCentre) bounds.top = yCentre;
179         else if(bounds.bottom < yCentre) bounds.right = yCentre;
180     }
181     if(!EMFDRV_WriteRecord( dev, &emr.emr ))
182         return FALSE;
183     EMFDRV_UpdateBBox( dev, &bounds );
184     return TRUE;
185 }
186 
187 
188 /***********************************************************************
189  *           EMFDRV_Arc
190  */
191 BOOL
192 EMFDRV_Arc( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
193             INT xstart, INT ystart, INT xend, INT yend )
194 {
195     return EMFDRV_ArcChordPie( dev, left, top, right, bottom, xstart, ystart,
196                                xend, yend, EMR_ARC );
197 }
198 
199 /***********************************************************************
200  *           EMFDRV_Pie
201  */
202 BOOL
203 EMFDRV_Pie( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
204             INT xstart, INT ystart, INT xend, INT yend )
205 {
206     return EMFDRV_ArcChordPie( dev, left, top, right, bottom, xstart, ystart,
207                                xend, yend, EMR_PIE );
208 }
209 
210 
211 /***********************************************************************
212  *           EMFDRV_Chord
213  */
214 BOOL
215 EMFDRV_Chord( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
216              INT xstart, INT ystart, INT xend, INT yend )
217 {
218     return EMFDRV_ArcChordPie( dev, left, top, right, bottom, xstart, ystart,
219                                xend, yend, EMR_CHORD );
220 }
221 
222 /***********************************************************************
223  *           EMFDRV_Ellipse
224  */
225 BOOL
226 EMFDRV_Ellipse( PHYSDEV dev, INT left, INT top, INT right, INT bottom )
227 {
228     EMRELLIPSE emr;
229     INT temp;
230     EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev;
231 
232     TRACE("%d,%d - %d,%d\n", left, top, right, bottom);
233 
234     if(left == right || top == bottom) return FALSE;
235 
236     if(left > right) {temp = left; left = right; right = temp;}
237     if(top > bottom) {temp = top; top = bottom; bottom = temp;}
238 
239     if(GetGraphicsMode(physDev->hdc) == GM_COMPATIBLE) {
240         right--;
241         bottom--;
242     }
243 
244     emr.emr.iType     = EMR_ELLIPSE;
245     emr.emr.nSize     = sizeof(emr);
246     emr.rclBox.left   = left;
247     emr.rclBox.top    = top;
248     emr.rclBox.right  = right;
249     emr.rclBox.bottom = bottom;
250 
251     EMFDRV_UpdateBBox( dev, &emr.rclBox );
252     return EMFDRV_WriteRecord( dev, &emr.emr );
253 }
254 
255 /***********************************************************************
256  *           EMFDRV_Rectangle
257  */
258 BOOL
259 EMFDRV_Rectangle(PHYSDEV dev, INT left, INT top, INT right, INT bottom)
260 {
261     EMRRECTANGLE emr;
262     INT temp;
263     EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev;
264 
265     TRACE("%d,%d - %d,%d\n", left, top, right, bottom);
266 
267     if(left == right || top == bottom) return FALSE;
268 
269     if(left > right) {temp = left; left = right; right = temp;}
270     if(top > bottom) {temp = top; top = bottom; bottom = temp;}
271 
272     if(GetGraphicsMode(physDev->hdc) == GM_COMPATIBLE) {
273         right--;
274         bottom--;
275     }
276 
277     emr.emr.iType     = EMR_RECTANGLE;
278     emr.emr.nSize     = sizeof(emr);
279     emr.rclBox.left   = left;
280     emr.rclBox.top    = top;
281     emr.rclBox.right  = right;
282     emr.rclBox.bottom = bottom;
283 
284     EMFDRV_UpdateBBox( dev, &emr.rclBox );
285     return EMFDRV_WriteRecord( dev, &emr.emr );
286 }
287 
288 /***********************************************************************
289  *           EMFDRV_RoundRect
290  */
291 BOOL
292 EMFDRV_RoundRect( PHYSDEV dev, INT left, INT top, INT right,
293                   INT bottom, INT ell_width, INT ell_height )
294 {
295     EMRROUNDRECT emr;
296     INT temp;
297     EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev;
298 
299     if(left == right || top == bottom) return FALSE;
300 
301     if(left > right) {temp = left; left = right; right = temp;}
302     if(top > bottom) {temp = top; top = bottom; bottom = temp;}
303 
304     if(GetGraphicsMode(physDev->hdc) == GM_COMPATIBLE) {
305         right--;
306         bottom--;
307     }
308 
309     emr.emr.iType     = EMR_ROUNDRECT;
310     emr.emr.nSize     = sizeof(emr);
311     emr.rclBox.left   = left;
312     emr.rclBox.top    = top;
313     emr.rclBox.right  = right;
314     emr.rclBox.bottom = bottom;
315     emr.szlCorner.cx  = ell_width;
316     emr.szlCorner.cy  = ell_height;
317 
318     EMFDRV_UpdateBBox( dev, &emr.rclBox );
319     return EMFDRV_WriteRecord( dev, &emr.emr );
320 }
321 
322 /***********************************************************************
323  *           EMFDRV_SetPixel
324  */
325 COLORREF
326 EMFDRV_SetPixel( PHYSDEV dev, INT x, INT y, COLORREF color )
327 {
328     EMRSETPIXELV emr;
329 
330     emr.emr.iType  = EMR_SETPIXELV;
331     emr.emr.nSize  = sizeof(emr);
332     emr.ptlPixel.x = x;
333     emr.ptlPixel.y = y;
334     emr.crColor = color;
335 
336     if (EMFDRV_WriteRecord( dev, &emr.emr )) {
337         RECTL bounds;
338         bounds.left = bounds.right = x;
339         bounds.top = bounds.bottom = y;
340         EMFDRV_UpdateBBox( dev, &bounds );
341         return color;
342     }
343     return -1;
344 }
345 
346 /**********************************************************************
347  *          EMFDRV_Polylinegon
348  *
349  * Helper for EMFDRV_Poly{line|gon}
350  */
351 static BOOL
352 EMFDRV_Polylinegon( PHYSDEV dev, const POINT* pt, INT count, DWORD iType )
353 {
354     EMRPOLYLINE *emr;
355     DWORD size;
356     INT i;
357     BOOL ret;
358 
359     size = sizeof(EMRPOLYLINE) + sizeof(POINTL) * (count - 1);
360 
361     emr = HeapAlloc( GetProcessHeap(), 0, size );
362     emr->emr.iType = iType;
363     emr->emr.nSize = size;
364 
365     emr->rclBounds.left = emr->rclBounds.right = pt[0].x;
366     emr->rclBounds.top = emr->rclBounds.bottom = pt[0].y;
367 
368     for(i = 1; i < count; i++) {
369         if(pt[i].x < emr->rclBounds.left)
370             emr->rclBounds.left = pt[i].x;
371         else if(pt[i].x > emr->rclBounds.right)
372             emr->rclBounds.right = pt[i].x;
373         if(pt[i].y < emr->rclBounds.top)
374             emr->rclBounds.top = pt[i].y;
375         else if(pt[i].y > emr->rclBounds.bottom)
376             emr->rclBounds.bottom = pt[i].y;
377     }
378 
379     emr->cptl = count;
380     memcpy(emr->aptl, pt, count * sizeof(POINTL));
381 
382     ret = EMFDRV_WriteRecord( dev, &emr->emr );
383     if(ret)
384         EMFDRV_UpdateBBox( dev, &emr->rclBounds );
385     HeapFree( GetProcessHeap(), 0, emr );
386     return ret;
387 }
388 
389 
390 /**********************************************************************
391  *          EMFDRV_Polylinegon16
392  *
393  * Helper for EMFDRV_Poly{line|gon}
394  *
395  *  This is not a legacy function!
396  *  We are using SHORT integers to save space.
397  */
398 static BOOL
399 EMFDRV_Polylinegon16( PHYSDEV dev, const POINT* pt, INT count, DWORD iType )
400 {
401     EMRPOLYLINE16 *emr;
402     DWORD size;
403     INT i;
404     BOOL ret;
405 
406     /* check whether all points fit in the SHORT int POINT structure */
407     for(i = 0; i < count; i++) {
408         if( ((pt[i].x+0x8000) & ~0xffff ) || 
409             ((pt[i].y+0x8000) & ~0xffff ) )
410             return FALSE;
411     }
412 
413     size = sizeof(EMRPOLYLINE16) + sizeof(POINTS) * (count - 1);
414 
415     emr = HeapAlloc( GetProcessHeap(), 0, size );
416     emr->emr.iType = iType;
417     emr->emr.nSize = size;
418 
419     emr->rclBounds.left = emr->rclBounds.right = pt[0].x;
420     emr->rclBounds.top = emr->rclBounds.bottom = pt[0].y;
421 
422     for(i = 1; i < count; i++) {
423         if(pt[i].x < emr->rclBounds.left)
424             emr->rclBounds.left = pt[i].x;
425         else if(pt[i].x > emr->rclBounds.right)
426             emr->rclBounds.right = pt[i].x;
427         if(pt[i].y < emr->rclBounds.top)
428             emr->rclBounds.top = pt[i].y;
429         else if(pt[i].y > emr->rclBounds.bottom)
430             emr->rclBounds.bottom = pt[i].y;
431     }
432 
433     emr->cpts = count;
434     for(i = 0; i < count; i++ ) {
435         emr->apts[i].x = pt[i].x;
436         emr->apts[i].y = pt[i].y;
437     }
438 
439     ret = EMFDRV_WriteRecord( dev, &emr->emr );
440     if(ret)
441         EMFDRV_UpdateBBox( dev, &emr->rclBounds );
442     HeapFree( GetProcessHeap(), 0, emr );
443     return ret;
444 }
445 
446 
447 /**********************************************************************
448  *          EMFDRV_Polyline
449  */
450 BOOL
451 EMFDRV_Polyline( PHYSDEV dev, const POINT* pt, INT count )
452 {
453     if( EMFDRV_Polylinegon16( dev, pt, count, EMR_POLYLINE16 ) )
454         return TRUE;
455     return EMFDRV_Polylinegon( dev, pt, count, EMR_POLYLINE );
456 }
457 
458 /**********************************************************************
459  *          EMFDRV_Polygon
460  */
461 BOOL
462 EMFDRV_Polygon( PHYSDEV dev, const POINT* pt, INT count )
463 {
464     if(count < 2) return FALSE;
465     if( EMFDRV_Polylinegon16( dev, pt, count, EMR_POLYGON16 ) )
466         return TRUE;
467     return EMFDRV_Polylinegon( dev, pt, count, EMR_POLYGON );
468 }
469 
470 
471 /**********************************************************************
472  *          EMFDRV_PolyPolylinegon
473  *
474  * Helper for EMFDRV_PolyPoly{line|gon}
475  */
476 static BOOL
477 EMFDRV_PolyPolylinegon( PHYSDEV dev, const POINT* pt, const INT* counts, UINT polys,
478                         DWORD iType)
479 {
480     EMRPOLYPOLYLINE *emr;
481     DWORD cptl = 0, poly, size;
482     INT point;
483     RECTL bounds;
484     const POINT *pts;
485     BOOL ret;
486 
487     bounds.left = bounds.right = pt[0].x;
488     bounds.top = bounds.bottom = pt[0].y;
489 
490     pts = pt;
491     for(poly = 0; poly < polys; poly++) {
492         cptl += counts[poly];
493         for(point = 0; point < counts[poly]; point++) {
494             if(bounds.left > pts->x) bounds.left = pts->x;
495             else if(bounds.right < pts->x) bounds.right = pts->x;
496             if(bounds.top > pts->y) bounds.top = pts->y;
497             else if(bounds.bottom < pts->y) bounds.bottom = pts->y;
498             pts++;
499         }
500     }
501 
502     size = sizeof(EMRPOLYPOLYLINE) + (polys - 1) * sizeof(DWORD) +
503       (cptl - 1) * sizeof(POINTL);
504 
505     emr = HeapAlloc( GetProcessHeap(), 0, size );
506 
507     emr->emr.iType = iType;
508     emr->emr.nSize = size;
509     emr->rclBounds = bounds;
510     emr->nPolys = polys;
511     emr->cptl = cptl;
512     memcpy(emr->aPolyCounts, counts, polys * sizeof(DWORD));
513     memcpy(emr->aPolyCounts + polys, pt, cptl * sizeof(POINTL));
514     ret = EMFDRV_WriteRecord( dev, &emr->emr );
515     if(ret)
516         EMFDRV_UpdateBBox( dev, &emr->rclBounds );
517     HeapFree( GetProcessHeap(), 0, emr );
518     return ret;
519 }
520 
521 /**********************************************************************
522  *          EMFDRV_PolyPolyline
523  */
524 BOOL
525 EMFDRV_PolyPolyline(PHYSDEV dev, const POINT* pt, const DWORD* counts, DWORD polys)
526 {
527     return EMFDRV_PolyPolylinegon( dev, pt, (const INT *)counts, polys,
528                                    EMR_POLYPOLYLINE );
529 }
530 
531 /**********************************************************************
532  *          EMFDRV_PolyPolygon
533  */
534 BOOL
535 EMFDRV_PolyPolygon( PHYSDEV dev, const POINT* pt, const INT* counts, UINT polys )
536 {
537     return EMFDRV_PolyPolylinegon( dev, pt, counts, polys, EMR_POLYPOLYGON );
538 }
539 
540 
541 /**********************************************************************
542  *          EMFDRV_ExtFloodFill
543  */
544 BOOL
545 EMFDRV_ExtFloodFill( PHYSDEV dev, INT x, INT y, COLORREF color, UINT fillType )
546 {
547     EMREXTFLOODFILL emr;
548 
549     emr.emr.iType = EMR_EXTFLOODFILL;
550     emr.emr.nSize = sizeof(emr);
551     emr.ptlStart.x = x;
552     emr.ptlStart.y = y;
553     emr.crColor = color;
554     emr.iMode = fillType;
555 
556     return EMFDRV_WriteRecord( dev, &emr.emr );
557 }
558 
559 
560 /*********************************************************************
561  *          EMFDRV_FillRgn
562  */
563 BOOL EMFDRV_FillRgn( PHYSDEV dev, HRGN hrgn, HBRUSH hbrush )
564 {
565     EMRFILLRGN *emr;
566     DWORD size, rgnsize, index;
567     BOOL ret;
568 
569     index = EMFDRV_CreateBrushIndirect( dev, hbrush );
570     if(!index) return FALSE;
571 
572     rgnsize = GetRegionData( hrgn, 0, NULL );
573     size = rgnsize + offsetof(EMRFILLRGN,RgnData);
574     emr = HeapAlloc( GetProcessHeap(), 0, size );
575 
576     GetRegionData( hrgn, rgnsize, (RGNDATA *)&emr->RgnData );
577 
578     emr->emr.iType = EMR_FILLRGN;
579     emr->emr.nSize = size;
580     emr->rclBounds.left   = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.left;
581     emr->rclBounds.top    = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.top;
582     emr->rclBounds.right  = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.right - 1;
583     emr->rclBounds.bottom = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.bottom - 1;
584     emr->cbRgnData = rgnsize;
585     emr->ihBrush = index;
586 
587     ret = EMFDRV_WriteRecord( dev, &emr->emr );
588     if(ret)
589         EMFDRV_UpdateBBox( dev, &emr->rclBounds );
590     HeapFree( GetProcessHeap(), 0, emr );
591     return ret;
592 }
593 /*********************************************************************
594  *          EMFDRV_FrameRgn
595  */
596 BOOL EMFDRV_FrameRgn( PHYSDEV dev, HRGN hrgn, HBRUSH hbrush, INT width, INT height )
597 {
598     EMRFRAMERGN *emr;
599     DWORD size, rgnsize, index;
600     BOOL ret;
601 
602     index = EMFDRV_CreateBrushIndirect( dev, hbrush );
603     if(!index) return FALSE;
604 
605     rgnsize = GetRegionData( hrgn, 0, NULL );
606     size = rgnsize + offsetof(EMRFRAMERGN,RgnData);
607     emr = HeapAlloc( GetProcessHeap(), 0, size );
608 
609     GetRegionData( hrgn, rgnsize, (RGNDATA *)&emr->RgnData );
610 
611     emr->emr.iType = EMR_FRAMERGN;
612     emr->emr.nSize = size;
613     emr->rclBounds.left   = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.left;
614     emr->rclBounds.top    = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.top;
615     emr->rclBounds.right  = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.right - 1;
616     emr->rclBounds.bottom = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.bottom - 1;
617     emr->cbRgnData = rgnsize;
618     emr->ihBrush = index;
619     emr->szlStroke.cx = width;
620     emr->szlStroke.cy = height;
621 
622     ret = EMFDRV_WriteRecord( dev, &emr->emr );
623     if(ret)
624         EMFDRV_UpdateBBox( dev, &emr->rclBounds );
625     HeapFree( GetProcessHeap(), 0, emr );
626     return ret;
627 }
628 
629 /*********************************************************************
630  *          EMFDRV_PaintInvertRgn
631  *
632  * Helper for EMFDRV_{Paint|Invert}Rgn
633  */
634 static BOOL EMFDRV_PaintInvertRgn( PHYSDEV dev, HRGN hrgn, DWORD iType )
635 {
636     EMRINVERTRGN *emr;
637     DWORD size, rgnsize;
638     BOOL ret;
639 
640 
641     rgnsize = GetRegionData( hrgn, 0, NULL );
642     size = rgnsize + offsetof(EMRINVERTRGN,RgnData);
643     emr = HeapAlloc( GetProcessHeap(), 0, size );
644 
645     GetRegionData( hrgn, rgnsize, (RGNDATA *)&emr->RgnData );
646 
647     emr->emr.iType = iType;
648     emr->emr.nSize = size;
649     emr->rclBounds.left   = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.left;
650     emr->rclBounds.top    = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.top;
651     emr->rclBounds.right  = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.right - 1;
652     emr->rclBounds.bottom = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.bottom - 1;
653     emr->cbRgnData = rgnsize;
654 
655     ret = EMFDRV_WriteRecord( dev, &emr->emr );
656     if(ret)
657         EMFDRV_UpdateBBox( dev, &emr->rclBounds );
658     HeapFree( GetProcessHeap(), 0, emr );
659     return ret;
660 }
661 
662 /**********************************************************************
663  *          EMFDRV_PaintRgn
664  */
665 BOOL
666 EMFDRV_PaintRgn( PHYSDEV dev, HRGN hrgn )
667 {
668     return EMFDRV_PaintInvertRgn( dev, hrgn, EMR_PAINTRGN );
669 }
670 
671 /**********************************************************************
672  *          EMFDRV_InvertRgn
673  */
674 BOOL
675 EMFDRV_InvertRgn( PHYSDEV dev, HRGN hrgn )
676 {
677     return EMFDRV_PaintInvertRgn( dev, hrgn, EMR_INVERTRGN );
678 }
679 
680 /**********************************************************************
681  *          EMFDRV_SetBkColor
682  */
683 COLORREF
684 EMFDRV_SetBkColor( PHYSDEV dev, COLORREF color )
685 {
686     EMRSETBKCOLOR emr;
687 
688     emr.emr.iType = EMR_SETBKCOLOR;
689     emr.emr.nSize = sizeof(emr);
690     emr.crColor = color;
691 
692     return EMFDRV_WriteRecord( dev, &emr.emr ) ? color : CLR_INVALID;
693 }
694 
695 
696 /**********************************************************************
697  *          EMFDRV_SetTextColor
698  */
699 COLORREF
700 EMFDRV_SetTextColor( PHYSDEV dev, COLORREF color )
701 {
702     EMRSETTEXTCOLOR emr;
703 
704     emr.emr.iType = EMR_SETTEXTCOLOR;
705     emr.emr.nSize = sizeof(emr);
706     emr.crColor = color;
707 
708     return EMFDRV_WriteRecord( dev, &emr.emr ) ? color : CLR_INVALID;
709 }
710 
711 /**********************************************************************
712  *          EMFDRV_ExtTextOut
713  */
714 BOOL EMFDRV_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags,
715                         const RECT *lprect, LPCWSTR str, UINT count,
716                         const INT *lpDx )
717 {
718     EMREXTTEXTOUTW *pemr;
719     DWORD nSize;
720     BOOL ret;
721     EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE*) dev;
722     int textHeight = 0;
723     int textWidth = 0;
724     const UINT textAlign = GetTextAlign(physDev->hdc);
725 
726     nSize = sizeof(*pemr) + ((count+1) & ~1) * sizeof(WCHAR) + count * sizeof(INT);
727 
728     TRACE("%s %s count %d nSize = %d\n", debugstr_wn(str, count),
729            wine_dbgstr_rect(lprect), count, nSize);
730     pemr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nSize);
731 
732     pemr->emr.iType = EMR_EXTTEXTOUTW;
733     pemr->emr.nSize = nSize;
734 
735     pemr->iGraphicsMode = GetGraphicsMode(physDev->hdc);
736     pemr->exScale = pemr->eyScale = 1.0; /* FIXME */
737 
738     pemr->emrtext.ptlReference.x = x;
739     pemr->emrtext.ptlReference.y = y;
740     pemr->emrtext.nChars = count;
741     pemr->emrtext.offString = sizeof(*pemr);
742     memcpy((char*)pemr + pemr->emrtext.offString, str, count * sizeof(WCHAR));
743     pemr->emrtext.fOptions = flags;
744     if(!lprect) {
745         pemr->emrtext.rcl.left = pemr->emrtext.rcl.top = 0;
746         pemr->emrtext.rcl.right = pemr->emrtext.rcl.bottom = -1;
747     } else {
748         pemr->emrtext.rcl.left = lprect->left;
749         pemr->emrtext.rcl.top = lprect->top;
750         pemr->emrtext.rcl.right = lprect->right;
751         pemr->emrtext.rcl.bottom = lprect->bottom;
752     }
753 
754     pemr->emrtext.offDx = pemr->emrtext.offString + ((count+1) & ~1) * sizeof(WCHAR);
755     if(lpDx) {
756         UINT i;
757         SIZE strSize;
758         memcpy((char*)pemr + pemr->emrtext.offDx, lpDx, count * sizeof(INT));
759         for (i = 0; i < count; i++) {
760             textWidth += lpDx[i];
761         }
762         if (GetTextExtentPoint32W(physDev->hdc, str, count, &strSize))
763             textHeight = strSize.cy;
764     }
765     else {
766         UINT i;
767         INT *dx = (INT *)((char*)pemr + pemr->emrtext.offDx);
768         SIZE charSize;
769         for (i = 0; i < count; i++) {
770             if (GetTextExtentPoint32W(physDev->hdc, str + i, 1, &charSize)) {
771                 dx[i] = charSize.cx;
772                 textWidth += charSize.cx;
773                 textHeight = max(textHeight, charSize.cy);
774             }
775         }
776     }
777 
778     if (!lprect)
779     {
780         pemr->rclBounds.left = pemr->rclBounds.top = 0;
781         pemr->rclBounds.right = pemr->rclBounds.bottom = -1;
782         goto no_bounds;
783     }
784 
785     switch (textAlign & (TA_LEFT | TA_RIGHT | TA_CENTER)) {
786     case TA_CENTER: {
787         pemr->rclBounds.left  = x - (textWidth / 2) - 1;
788         pemr->rclBounds.right = x + (textWidth / 2) + 1;
789         break;
790     }
791     case TA_RIGHT: {
792         pemr->rclBounds.left  = x - textWidth - 1;
793         pemr->rclBounds.right = x;
794         break;
795     }
796     default: { /* TA_LEFT */
797         pemr->rclBounds.left  = x;
798         pemr->rclBounds.right = x + textWidth + 1;
799     }
800     }
801 
802     switch (textAlign & (TA_TOP | TA_BOTTOM | TA_BASELINE)) {
803     case TA_BASELINE: {
804         TEXTMETRICW tm;
805         if (!GetTextMetricsW(physDev->hdc, &tm))
806             tm.tmDescent = 0;
807         /* Play safe here... it's better to have a bounding box */
808         /* that is too big than too small. */
809         pemr->rclBounds.top    = y - textHeight - 1;
810         pemr->rclBounds.bottom = y + tm.tmDescent + 1;
811         break;
812     }
813     case TA_BOTTOM: {
814         pemr->rclBounds.top    = y - textHeight - 1;
815         pemr->rclBounds.bottom = y;
816         break;
817     }
818     default: { /* TA_TOP */
819         pemr->rclBounds.top    = y;
820         pemr->rclBounds.bottom = y + textHeight + 1;
821     }
822     }
823 
824 no_bounds:
825     ret = EMFDRV_WriteRecord( dev, &pemr->emr );
826     if(ret)
827         EMFDRV_UpdateBBox( dev, &pemr->rclBounds );
828     HeapFree( GetProcessHeap(), 0, pemr );
829     return ret;
830 }
831 
832 /**********************************************************************
833  *          EMFDRV_SetArcDirection
834  */
835 INT EMFDRV_SetArcDirection(PHYSDEV dev, INT arcDirection)
836 {
837     EMRSETARCDIRECTION emr;
838 
839     emr.emr.iType = EMR_SETARCDIRECTION;
840     emr.emr.nSize = sizeof(emr);
841     emr.iArcDirection = arcDirection;
842 
843     EMFDRV_WriteRecord(dev, &emr.emr);
844 
845     /* We don't know the old arc direction and we don't care... */ 
846     return 0;
847 }
848 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.