7efa7d87cf672a517f2a52d1ffa28222e4a6a031
[framework/graphics/cairo.git] / src / win32 / cairo-win32-display-surface.c
1 /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
2 /* Cairo - a vector graphics library with display and print output
3  *
4  * Copyright © 2005 Red Hat, Inc.
5  * Copyright © 2012 Intel Corporation
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it either under the terms of the GNU Lesser General Public
9  * License version 2.1 as published by the Free Software Foundation
10  * (the "LGPL") or, at your option, under the terms of the Mozilla
11  * Public License Version 1.1 (the "MPL"). If you do not alter this
12  * notice, a recipient may use your version of this file under either
13  * the MPL or the LGPL.
14  *
15  * You should have received a copy of the LGPL along with this library
16  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
18  * You should have received a copy of the MPL along with this library
19  * in the file COPYING-MPL-1.1
20  *
21  * The contents of this file are subject to the Mozilla Public License
22  * Version 1.1 (the "License"); you may not use this file except in
23  * compliance with the License. You may obtain a copy of the License at
24  * http://www.mozilla.org/MPL/
25  *
26  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
27  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
28  * the specific language governing rights and limitations.
29  *
30  * The Original Code is the cairo graphics library.
31  *
32  * The Initial Developer of the Original Code is Red Hat, Inc.
33  *
34  * Contributor(s):
35  *      Owen Taylor <otaylor@redhat.com>
36  *      Stuart Parmenter <stuart@mozilla.com>
37  *      Vladimir Vukicevic <vladimir@pobox.com>
38  */
39
40 #define WIN32_LEAN_AND_MEAN
41 /* We require Windows 2000 features such as ETO_PDY */
42 #if !defined(WINVER) || (WINVER < 0x0500)
43 # define WINVER 0x0500
44 #endif
45 #if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
46 # define _WIN32_WINNT 0x0500
47 #endif
48
49 #include "cairoint.h"
50
51 #include "cairo-clip-private.h"
52 #include "cairo-composite-rectangles-private.h"
53 #include "cairo-compositor-private.h"
54 #include "cairo-damage-private.h"
55 #include "cairo-default-context-private.h"
56 #include "cairo-error-private.h"
57 #include "cairo-image-surface-inline.h"
58 #include "cairo-paginated-private.h"
59 #include "cairo-pattern-private.h"
60 #include "cairo-win32-private.h"
61 #include "cairo-scaled-font-subsets-private.h"
62 #include "cairo-surface-fallback-private.h"
63 #include "cairo-surface-backend-private.h"
64
65 #include <wchar.h>
66 #include <windows.h>
67
68 #if defined(__MINGW32__) && !defined(ETO_PDY)
69 # define ETO_PDY 0x2000
70 #endif
71
72 #define PELS_72DPI  ((LONG)(72. / 0.0254))
73
74 /**
75  * SECTION:cairo-win32
76  * @Title: Win32 Surfaces
77  * @Short_Description: Microsoft Windows surface support
78  * @See_Also: #cairo_surface_t
79  *
80  * The Microsoft Windows surface is used to render cairo graphics to
81  * Microsoft Windows windows, bitmaps, and printing device contexts.
82  *
83  * The surface returned by cairo_win32_printing_surface_create() is of surface
84  * type %CAIRO_SURFACE_TYPE_WIN32_PRINTING and is a multi-page vector surface
85  * type.
86  *
87  * The surface returned by the other win32 constructors is of surface type
88  * %CAIRO_SURFACE_TYPE_WIN32 and is a raster surface type.
89  **/
90
91 /**
92  * CAIRO_HAS_WIN32_SURFACE:
93  *
94  * Defined if the Microsoft Windows surface backend is available.
95  * This macro can be used to conditionally compile backend-specific code.
96  *
97  * Since: 1.0
98  **/
99
100 static const cairo_surface_backend_t cairo_win32_display_surface_backend;
101
102 static cairo_status_t
103 _create_dc_and_bitmap (cairo_win32_display_surface_t *surface,
104                        HDC                    original_dc,
105                        cairo_format_t         format,
106                        int                    width,
107                        int                    height,
108                        unsigned char        **bits_out,
109                        int                   *rowstride_out)
110 {
111     cairo_status_t status;
112
113     BITMAPINFO *bitmap_info = NULL;
114     struct {
115         BITMAPINFOHEADER bmiHeader;
116         RGBQUAD bmiColors[2];
117     } bmi_stack;
118     void *bits;
119
120     int num_palette = 0;        /* Quiet GCC */
121     int i;
122
123     surface->win32.dc = NULL;
124     surface->bitmap = NULL;
125     surface->is_dib = FALSE;
126
127     switch (format) {
128     default:
129     case CAIRO_FORMAT_INVALID:
130     case CAIRO_FORMAT_RGB16_565:
131     case CAIRO_FORMAT_RGB30:
132         return _cairo_error (CAIRO_STATUS_INVALID_FORMAT);
133     case CAIRO_FORMAT_ARGB32:
134     case CAIRO_FORMAT_RGB24:
135         num_palette = 0;
136         break;
137
138     case CAIRO_FORMAT_A8:
139         num_palette = 256;
140         break;
141
142     case CAIRO_FORMAT_A1:
143         num_palette = 2;
144         break;
145     }
146
147     if (num_palette > 2) {
148         bitmap_info = _cairo_malloc_ab_plus_c (num_palette, sizeof(RGBQUAD), sizeof(BITMAPINFOHEADER));
149         if (!bitmap_info)
150             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
151     } else {
152         bitmap_info = (BITMAPINFO *)&bmi_stack;
153     }
154
155     bitmap_info->bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
156     bitmap_info->bmiHeader.biWidth = width == 0 ? 1 : width;
157     bitmap_info->bmiHeader.biHeight = height == 0 ? -1 : - height; /* top-down */
158     bitmap_info->bmiHeader.biSizeImage = 0;
159     bitmap_info->bmiHeader.biXPelsPerMeter = PELS_72DPI; /* unused here */
160     bitmap_info->bmiHeader.biYPelsPerMeter = PELS_72DPI; /* unused here */
161     bitmap_info->bmiHeader.biPlanes = 1;
162
163     switch (format) {
164     case CAIRO_FORMAT_INVALID:
165     case CAIRO_FORMAT_RGB16_565:
166     case CAIRO_FORMAT_RGB30:
167         ASSERT_NOT_REACHED;
168     /* We can't create real RGB24 bitmaps because something seems to
169      * break if we do, especially if we don't set up an image
170      * fallback.  It could be a bug with using a 24bpp pixman image
171      * (and creating one with masks).  So treat them like 32bpp.
172      * Note: This causes problems when using BitBlt/AlphaBlend/etc!
173      * see end of file.
174      */
175     case CAIRO_FORMAT_RGB24:
176     case CAIRO_FORMAT_ARGB32:
177         bitmap_info->bmiHeader.biBitCount = 32;
178         bitmap_info->bmiHeader.biCompression = BI_RGB;
179         bitmap_info->bmiHeader.biClrUsed = 0;   /* unused */
180         bitmap_info->bmiHeader.biClrImportant = 0;
181         break;
182
183     case CAIRO_FORMAT_A8:
184         bitmap_info->bmiHeader.biBitCount = 8;
185         bitmap_info->bmiHeader.biCompression = BI_RGB;
186         bitmap_info->bmiHeader.biClrUsed = 256;
187         bitmap_info->bmiHeader.biClrImportant = 0;
188
189         for (i = 0; i < 256; i++) {
190             bitmap_info->bmiColors[i].rgbBlue = i;
191             bitmap_info->bmiColors[i].rgbGreen = i;
192             bitmap_info->bmiColors[i].rgbRed = i;
193             bitmap_info->bmiColors[i].rgbReserved = 0;
194         }
195         break;
196
197     case CAIRO_FORMAT_A1:
198         bitmap_info->bmiHeader.biBitCount = 1;
199         bitmap_info->bmiHeader.biCompression = BI_RGB;
200         bitmap_info->bmiHeader.biClrUsed = 2;
201         bitmap_info->bmiHeader.biClrImportant = 0;
202
203         for (i = 0; i < 2; i++) {
204             bitmap_info->bmiColors[i].rgbBlue = i * 255;
205             bitmap_info->bmiColors[i].rgbGreen = i * 255;
206             bitmap_info->bmiColors[i].rgbRed = i * 255;
207             bitmap_info->bmiColors[i].rgbReserved = 0;
208         }
209         break;
210     }
211
212     surface->win32.dc = CreateCompatibleDC (original_dc);
213     if (!surface->win32.dc)
214         goto FAIL;
215
216     surface->bitmap = CreateDIBSection (surface->win32.dc,
217                                         bitmap_info,
218                                         DIB_RGB_COLORS,
219                                         &bits,
220                                         NULL, 0);
221     if (!surface->bitmap)
222         goto FAIL;
223
224     surface->is_dib = TRUE;
225
226     GdiFlush();
227
228     surface->saved_dc_bitmap = SelectObject (surface->win32.dc,
229                                              surface->bitmap);
230     if (!surface->saved_dc_bitmap)
231         goto FAIL;
232
233     if (bitmap_info && num_palette > 2)
234         free (bitmap_info);
235
236     if (bits_out)
237         *bits_out = bits;
238
239     if (rowstride_out) {
240         /* Windows bitmaps are padded to 32-bit (dword) boundaries */
241         switch (format) {
242         case CAIRO_FORMAT_INVALID:
243         case CAIRO_FORMAT_RGB16_565:
244         case CAIRO_FORMAT_RGB30:
245             ASSERT_NOT_REACHED;
246         case CAIRO_FORMAT_ARGB32:
247         case CAIRO_FORMAT_RGB24:
248             *rowstride_out = 4 * width;
249             break;
250
251         case CAIRO_FORMAT_A8:
252             *rowstride_out = (width + 3) & ~3;
253             break;
254
255         case CAIRO_FORMAT_A1:
256             *rowstride_out = ((width + 31) & ~31) / 8;
257             break;
258         }
259     }
260
261     surface->win32.flags = _cairo_win32_flags_for_dc (surface->win32.dc);
262
263     return CAIRO_STATUS_SUCCESS;
264
265  FAIL:
266     status = _cairo_win32_print_gdi_error (__FUNCTION__);
267
268     if (bitmap_info && num_palette > 2)
269         free (bitmap_info);
270
271     if (surface->saved_dc_bitmap) {
272         SelectObject (surface->win32.dc, surface->saved_dc_bitmap);
273         surface->saved_dc_bitmap = NULL;
274     }
275
276     if (surface->bitmap) {
277         DeleteObject (surface->bitmap);
278         surface->bitmap = NULL;
279     }
280
281     if (surface->win32.dc) {
282         DeleteDC (surface->win32.dc);
283         surface->win32.dc = NULL;
284     }
285
286     return status;
287 }
288
289 static cairo_surface_t *
290 _cairo_win32_display_surface_create_for_dc (HDC             original_dc,
291                                             cairo_format_t  format,
292                                             int             width,
293                                             int             height)
294 {
295     cairo_status_t status;
296     cairo_device_t *device;
297     cairo_win32_display_surface_t *surface;
298     unsigned char *bits;
299     int rowstride;
300
301     surface = malloc (sizeof (*surface));
302     if (surface == NULL)
303         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
304
305     surface->fallback = NULL;
306
307     status = _create_dc_and_bitmap (surface, original_dc, format,
308                                     width, height,
309                                     &bits, &rowstride);
310     if (status)
311         goto FAIL;
312
313     surface->image = cairo_image_surface_create_for_data (bits, format,
314                                                           width, height, rowstride);
315     status = surface->image->status;
316     if (status)
317         goto FAIL;
318
319     _cairo_image_surface_set_parent (to_image_surface(surface->image),
320                                      &surface->win32.base);
321
322     surface->win32.format = format;
323
324     surface->win32.extents.x = 0;
325     surface->win32.extents.y = 0;
326     surface->win32.extents.width = width;
327     surface->win32.extents.height = height;
328
329     surface->initial_clip_rgn = NULL;
330     surface->had_simple_clip = FALSE;
331
332     device = _cairo_win32_device_get ();
333
334     _cairo_surface_init (&surface->win32.base,
335                          &cairo_win32_display_surface_backend,
336                          device,
337                          _cairo_content_from_format (format));
338
339     cairo_device_destroy (device);
340
341     return &surface->win32.base;
342
343  FAIL:
344     if (surface->bitmap) {
345         SelectObject (surface->win32.dc, surface->saved_dc_bitmap);
346         DeleteObject (surface->bitmap);
347         DeleteDC (surface->win32.dc);
348     }
349     free (surface);
350
351     return _cairo_surface_create_in_error (status);
352 }
353
354 static cairo_surface_t *
355 _cairo_win32_display_surface_create_similar (void           *abstract_src,
356                                              cairo_content_t content,
357                                              int             width,
358                                              int             height)
359 {
360     cairo_win32_display_surface_t *src = abstract_src;
361     cairo_format_t format = _cairo_format_from_content (content);
362     cairo_surface_t *new_surf = NULL;
363
364     /* We force a DIB always if:
365      * - we need alpha; or
366      * - the parent is a DIB; or
367      * - the parent is for printing (because we don't care about the
368      *   bit depth at that point)
369      *
370      * We also might end up with a DIB even if a DDB is requested if
371      * DDB creation failed due to out of memory.
372      */
373     if (!(src->is_dib || content & CAIRO_CONTENT_ALPHA)) {
374         /* try to create a ddb */
375         new_surf = cairo_win32_surface_create_with_ddb (src->win32.dc, CAIRO_FORMAT_RGB24, width, height);
376
377         if (new_surf->status)
378             new_surf = NULL;
379     }
380
381     if (new_surf == NULL) {
382         new_surf = _cairo_win32_display_surface_create_for_dc (src->win32.dc, format, width, height);
383     }
384
385     return new_surf;
386 }
387
388 static cairo_surface_t *
389 _cairo_win32_display_surface_create_similar_image (void     *abstract_other,
390                                                    cairo_format_t format,
391                                                    int       width,
392                                                    int       height)
393 {
394     cairo_win32_display_surface_t *surface = abstract_other;
395
396     surface = (cairo_win32_display_surface_t *)
397         _cairo_win32_display_surface_create_for_dc (surface->win32.dc,
398                                                     format, width, height);
399     if (surface->win32.base.status)
400         return &surface->win32.base;
401
402     return surface->image;
403 }
404
405 static cairo_status_t
406 _cairo_win32_display_surface_finish (void *abstract_surface)
407 {
408     cairo_win32_display_surface_t *surface = abstract_surface;
409
410     if (surface->image) {
411         /* Unhook ourselves first to avoid the double-unref from the image */
412         to_image_surface(surface->image)->parent = NULL;
413         cairo_surface_finish (surface->image);
414         cairo_surface_destroy (surface->image);
415     }
416
417     /* If we created the Bitmap and DC, destroy them */
418     if (surface->bitmap) {
419         SelectObject (surface->win32.dc, surface->saved_dc_bitmap);
420         DeleteObject (surface->bitmap);
421         DeleteDC (surface->win32.dc);
422     }
423
424     if (surface->initial_clip_rgn)
425         DeleteObject (surface->initial_clip_rgn);
426
427     return CAIRO_STATUS_SUCCESS;
428 }
429
430 static cairo_surface_t *
431 _cairo_win32_display_surface_map_to_image (void                    *abstract_surface,
432                                            const cairo_rectangle_int_t   *extents)
433 {
434     cairo_win32_display_surface_t *surface = abstract_surface;
435     cairo_status_t status;
436
437     TRACE ((stderr, "%s (surface=%d)\n",
438             __FUNCTION__, surface->win32.base.unique_id));
439
440     if (surface->image)
441         goto done;
442
443     if (surface->fallback == NULL) {
444         surface->fallback =
445             _cairo_win32_display_surface_create_for_dc (surface->win32.dc,
446                                                         surface->win32.format,
447                                                         surface->win32.extents.width,
448                                                         surface->win32.extents.height);
449         if (unlikely (status = surface->fallback->status))
450             goto err;
451
452         if (!BitBlt (to_win32_surface(surface->fallback)->dc,
453                      0, 0,
454                      surface->win32.extents.width,
455                      surface->win32.extents.height,
456                      surface->win32.dc,
457                      0, 0,
458                      SRCCOPY)) {
459             status = _cairo_error (CAIRO_STATUS_DEVICE_ERROR);
460             goto err;
461         }
462     }
463
464     surface = to_win32_display_surface (surface->fallback);
465 done:
466     GdiFlush();
467     return _cairo_image_surface_map_to_image (surface->image, extents);
468
469 err:
470     cairo_surface_destroy (surface->fallback);
471     surface->fallback = NULL;
472
473     return _cairo_surface_create_in_error (status);
474 }
475
476 static cairo_int_status_t
477 _cairo_win32_display_surface_unmap_image (void                    *abstract_surface,
478                                           cairo_image_surface_t   *image)
479 {
480     cairo_win32_display_surface_t *surface = abstract_surface;
481
482     /* Delay the download until the next flush, which means we also need
483      * to make sure our sources rare flushed.
484      */
485     TRACE ((stderr, "%s (surface=%d)\n",
486             __FUNCTION__, to_win32_surface(surface)->base.unique_id));
487
488     if (surface->fallback) {
489         cairo_rectangle_int_t r;
490
491         r.x = image->base.device_transform_inverse.x0;
492         r.y = image->base.device_transform_inverse.y0;
493         r.width  = image->width;
494         r.height = image->height;
495
496         TRACE ((stderr, "%s: adding damage (%d,%d)x(%d,%d)\n",
497                 __FUNCTION__, r.x, r.y, r.width, r.height));
498         surface->fallback->damage =
499             _cairo_damage_add_rectangle (surface->fallback->damage, &r);
500     }
501
502     return CAIRO_INT_STATUS_SUCCESS;
503 }
504
505 static cairo_status_t
506 _cairo_win32_display_surface_flush (void *abstract_surface)
507 {
508     cairo_win32_display_surface_t *surface = abstract_surface;
509     cairo_status_t status = CAIRO_STATUS_SUCCESS;
510
511     TRACE ((stderr, "%s (surface=%d)\n",
512             __FUNCTION__, surface->win32.base.unique_id));
513     if (surface->fallback == NULL)
514         return CAIRO_STATUS_SUCCESS;
515
516     if (surface->fallback->damage) {
517         cairo_win32_display_surface_t *fallback;
518         cairo_damage_t *damage;
519
520         damage = _cairo_damage_reduce (surface->fallback->damage);
521         surface->fallback->damage = NULL;
522
523         fallback = to_win32_display_surface (surface->fallback);
524         assert (fallback->image);
525
526         TRACE ((stderr, "%s: flushing damage x %d\n", __FUNCTION__,
527                 damage->region ? cairo_region_num_rectangles (damage->region) : 0));
528
529         if (damage->status) {
530             if (!BitBlt (surface->win32.dc,
531                          0, 0,
532                          surface->win32.extents.width,
533                          surface->win32.extents.height,
534                          fallback->win32.dc,
535                          0, 0,
536                          SRCCOPY))
537                 status = _cairo_win32_print_gdi_error (__FUNCTION__);
538         } else if (damage->region) {
539             int n = cairo_region_num_rectangles (damage->region), i;
540             for (i = 0; i < n; i++) {
541                 cairo_rectangle_int_t rect;
542
543                 cairo_region_get_rectangle (damage->region, i, &rect);
544                 TRACE ((stderr, "%s: damage (%d,%d)x(%d,%d)\n", __FUNCTION__,
545                         rect.x, rect.y,
546                         rect.width, rect.height));
547                 if (!BitBlt (surface->win32.dc,
548                              rect.x, rect.y,
549                              rect.width, rect.height,
550                              fallback->win32.dc,
551                              rect.x, rect.y,
552                              SRCCOPY)) {
553                     status = _cairo_win32_print_gdi_error (__FUNCTION__);
554                     break;
555                 }
556             }
557         }
558         _cairo_damage_destroy (damage);
559     } else {
560         cairo_surface_destroy (surface->fallback);
561         surface->fallback = NULL;
562     }
563
564     return status;
565 }
566
567 static cairo_status_t
568 _cairo_win32_display_surface_mark_dirty (void *abstract_surface,
569                                          int x, int y, int width, int height)
570 {
571     _cairo_win32_display_surface_discard_fallback (abstract_surface);
572     return CAIRO_STATUS_SUCCESS;
573 }
574
575 static cairo_int_status_t
576 _cairo_win32_save_initial_clip (HDC hdc, cairo_win32_display_surface_t *surface)
577 {
578     RECT rect;
579     int clipBoxType;
580     int gm;
581     XFORM saved_xform;
582
583     /* GetClipBox/GetClipRgn and friends interact badly with a world transform
584      * set.  GetClipBox returns values in logical (transformed) coordinates;
585      * it's unclear what GetClipRgn returns, because the region is empty in the
586      * case of a SIMPLEREGION clip, but I assume device (untransformed) coordinates.
587      * Similarly, IntersectClipRect works in logical units, whereas SelectClipRgn
588      * works in device units.
589      *
590      * So, avoid the whole mess and get rid of the world transform
591      * while we store our initial data and when we restore initial coordinates.
592      *
593      * XXX we may need to modify x/y by the ViewportOrg or WindowOrg
594      * here in GM_COMPATIBLE; unclear.
595      */
596     gm = GetGraphicsMode (hdc);
597     if (gm == GM_ADVANCED) {
598         GetWorldTransform (hdc, &saved_xform);
599         ModifyWorldTransform (hdc, NULL, MWT_IDENTITY);
600     }
601
602     clipBoxType = GetClipBox (hdc, &rect);
603     if (clipBoxType == ERROR) {
604         _cairo_win32_print_gdi_error (__FUNCTION__);
605         SetGraphicsMode (hdc, gm);
606         /* XXX: Can we make a more reasonable guess at the error cause here? */
607         return _cairo_error (CAIRO_STATUS_DEVICE_ERROR);
608     }
609
610     surface->win32.extents.x = rect.left;
611     surface->win32.extents.y = rect.top;
612     surface->win32.extents.width = rect.right - rect.left;
613     surface->win32.extents.height = rect.bottom - rect.top;
614
615     surface->initial_clip_rgn = NULL;
616     surface->had_simple_clip = FALSE;
617
618     if (clipBoxType == COMPLEXREGION) {
619         surface->initial_clip_rgn = CreateRectRgn (0, 0, 0, 0);
620         if (GetClipRgn (hdc, surface->initial_clip_rgn) <= 0) {
621             DeleteObject(surface->initial_clip_rgn);
622             surface->initial_clip_rgn = NULL;
623         }
624     } else if (clipBoxType == SIMPLEREGION) {
625         surface->had_simple_clip = TRUE;
626     }
627
628     if (gm == GM_ADVANCED)
629         SetWorldTransform (hdc, &saved_xform);
630
631     return CAIRO_STATUS_SUCCESS;
632 }
633
634 cairo_status_t
635 _cairo_win32_display_surface_set_clip (cairo_win32_display_surface_t *surface,
636                                        cairo_clip_t *clip)
637 {
638     char stack[512];
639     cairo_rectangle_int_t extents;
640     int num_rects;
641     RGNDATA *data;
642     size_t data_size;
643     RECT *rects;
644     int i;
645     HRGN gdi_region;
646     cairo_status_t status;
647     cairo_region_t *region;
648
649     /* The semantics we want is that any clip set by cairo combines
650      * is intersected with the clip on device context that the
651      * surface was created for. To implement this, we need to
652      * save the original clip when first setting a clip on surface.
653      */
654
655     assert (_cairo_clip_is_region (clip));
656     region = _cairo_clip_get_region (clip);
657     if (region == NULL)
658         return CAIRO_STATUS_SUCCESS;
659
660     cairo_region_get_extents (region, &extents);
661     num_rects = cairo_region_num_rectangles (region);
662
663     /* XXX see notes in _cairo_win32_save_initial_clip --
664      * this code will interact badly with a HDC which had an initial
665      * world transform -- we should probably manually transform the
666      * region rects, because SelectClipRgn takes device units, not
667      * logical units (unlike IntersectClipRect).
668      */
669
670     data_size = sizeof (RGNDATAHEADER) + num_rects * sizeof (RECT);
671     if (data_size > sizeof (stack)) {
672         data = malloc (data_size);
673         if (!data)
674             return _cairo_error(CAIRO_STATUS_NO_MEMORY);
675     } else
676         data = (RGNDATA *)stack;
677
678     data->rdh.dwSize = sizeof (RGNDATAHEADER);
679     data->rdh.iType = RDH_RECTANGLES;
680     data->rdh.nCount = num_rects;
681     data->rdh.nRgnSize = num_rects * sizeof (RECT);
682     data->rdh.rcBound.left = extents.x;
683     data->rdh.rcBound.top = extents.y;
684     data->rdh.rcBound.right = extents.x + extents.width;
685     data->rdh.rcBound.bottom = extents.y + extents.height;
686
687     rects = (RECT *)data->Buffer;
688     for (i = 0; i < num_rects; i++) {
689         cairo_rectangle_int_t rect;
690
691         cairo_region_get_rectangle (region, i, &rect);
692
693         rects[i].left   = rect.x;
694         rects[i].top    = rect.y;
695         rects[i].right  = rect.x + rect.width;
696         rects[i].bottom = rect.y + rect.height;
697     }
698
699     gdi_region = ExtCreateRegion (NULL, data_size, data);
700     if ((char *)data != stack)
701         free (data);
702
703     if (!gdi_region)
704         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
705
706     /* AND the new region into our DC */
707     status = CAIRO_STATUS_SUCCESS;
708     if (ExtSelectClipRgn (surface->win32.dc, gdi_region, RGN_AND) == ERROR)
709         status = _cairo_win32_print_gdi_error (__FUNCTION__);
710
711     DeleteObject (gdi_region);
712
713     return status;
714 }
715
716 void
717 _cairo_win32_display_surface_unset_clip (cairo_win32_display_surface_t *surface)
718 {
719     XFORM saved_xform;
720     int gm = GetGraphicsMode (surface->win32.dc);
721     if (gm == GM_ADVANCED) {
722         GetWorldTransform (surface->win32.dc, &saved_xform);
723         ModifyWorldTransform (surface->win32.dc, NULL, MWT_IDENTITY);
724     }
725
726     /* initial_clip_rgn will either be a real region or NULL (which means reset to no clip region) */
727     SelectClipRgn (surface->win32.dc, surface->initial_clip_rgn);
728
729     if (surface->had_simple_clip) {
730         /* then if we had a simple clip, intersect */
731         IntersectClipRect (surface->win32.dc,
732                            surface->win32.extents.x,
733                            surface->win32.extents.y,
734                            surface->win32.extents.x + surface->win32.extents.width,
735                            surface->win32.extents.y + surface->win32.extents.height);
736     }
737
738     if (gm == GM_ADVANCED)
739         SetWorldTransform (surface->win32.dc, &saved_xform);
740 }
741
742 void
743 _cairo_win32_display_surface_discard_fallback (cairo_win32_display_surface_t *surface)
744 {
745     if (surface->fallback) {
746         TRACE ((stderr, "%s (surface=%d)\n",
747                 __FUNCTION__, surface->win32.base.unique_id));
748
749         cairo_surface_destroy (surface->fallback);
750         surface->fallback = NULL;
751     }
752 }
753
754 static cairo_int_status_t
755 _cairo_win32_display_surface_paint (void                        *surface,
756                                     cairo_operator_t             op,
757                                     const cairo_pattern_t       *source,
758                                     const cairo_clip_t          *clip)
759 {
760     cairo_win32_device_t *device = to_win32_device_from_surface (surface);
761
762     TRACE ((stderr, "%s (surface=%d)\n",
763             __FUNCTION__, to_win32_surface(surface)->base.unique_id));
764
765     if (clip == NULL &&
766         (op == CAIRO_OPERATOR_SOURCE || op == CAIRO_OPERATOR_CLEAR))
767         _cairo_win32_display_surface_discard_fallback (surface);
768
769     return _cairo_compositor_paint (device->compositor,
770                                     surface, op, source, clip);
771 }
772
773 static cairo_int_status_t
774 _cairo_win32_display_surface_mask (void                         *surface,
775                                    cairo_operator_t              op,
776                                    const cairo_pattern_t        *source,
777                                    const cairo_pattern_t        *mask,
778                                    const cairo_clip_t           *clip)
779 {
780     cairo_win32_device_t *device = to_win32_device_from_surface (surface);
781
782     TRACE ((stderr, "%s (surface=%d)\n",
783             __FUNCTION__, to_win32_surface(surface)->base.unique_id));
784
785     if (clip == NULL && op == CAIRO_OPERATOR_SOURCE)
786         _cairo_win32_display_surface_discard_fallback (surface);
787
788     return _cairo_compositor_mask (device->compositor,
789                                    surface, op, source, mask, clip);
790 }
791
792 static cairo_int_status_t
793 _cairo_win32_display_surface_stroke (void                       *surface,
794                                      cairo_operator_t            op,
795                                      const cairo_pattern_t      *source,
796                                      const cairo_path_fixed_t   *path,
797                                      const cairo_stroke_style_t *style,
798                                      const cairo_matrix_t       *ctm,
799                                      const cairo_matrix_t       *ctm_inverse,
800                                      double                      tolerance,
801                                      cairo_antialias_t           antialias,
802                                      const cairo_clip_t         *clip)
803 {
804     cairo_win32_device_t *device = to_win32_device_from_surface (surface);
805
806     TRACE ((stderr, "%s (surface=%d)\n",
807             __FUNCTION__, to_win32_surface(surface)->base.unique_id));
808
809     return _cairo_compositor_stroke (device->compositor, surface,
810                                      op, source, path,
811                                      style, ctm, ctm_inverse,
812                                      tolerance, antialias, clip);
813 }
814
815 static cairo_int_status_t
816 _cairo_win32_display_surface_fill (void                         *surface,
817                                    cairo_operator_t              op,
818                                    const cairo_pattern_t        *source,
819                                    const cairo_path_fixed_t     *path,
820                                    cairo_fill_rule_t             fill_rule,
821                                    double                        tolerance,
822                                    cairo_antialias_t             antialias,
823                                    const cairo_clip_t           *clip)
824 {
825     cairo_win32_device_t *device = to_win32_device_from_surface (surface);
826
827     TRACE ((stderr, "%s (surface=%d)\n",
828             __FUNCTION__, to_win32_surface(surface)->base.unique_id));
829
830     return _cairo_compositor_fill (device->compositor, surface,
831                                    op, source, path,
832                                    fill_rule, tolerance, antialias,
833                                    clip);
834 }
835
836 static cairo_int_status_t
837 _cairo_win32_display_surface_glyphs (void                       *surface,
838                                      cairo_operator_t            op,
839                                      const cairo_pattern_t      *source,
840                                      cairo_glyph_t              *glyphs,
841                                      int                         num_glyphs,
842                                      cairo_scaled_font_t        *scaled_font,
843                                      const cairo_clip_t         *clip)
844 {
845     cairo_win32_device_t *device = to_win32_device_from_surface (surface);
846
847     TRACE ((stderr, "%s (surface=%d)\n",
848             __FUNCTION__, to_win32_surface(surface)->base.unique_id));
849
850     return _cairo_compositor_glyphs (device->compositor, surface,
851                                      op, source,
852                                      glyphs, num_glyphs, scaled_font,
853                                      clip);
854 }
855
856 static const cairo_surface_backend_t cairo_win32_display_surface_backend = {
857     CAIRO_SURFACE_TYPE_WIN32,
858     _cairo_win32_display_surface_finish,
859
860     _cairo_default_context_create,
861
862     _cairo_win32_display_surface_create_similar,
863     _cairo_win32_display_surface_create_similar_image,
864     _cairo_win32_display_surface_map_to_image,
865     _cairo_win32_display_surface_unmap_image,
866
867     _cairo_surface_default_source,
868     _cairo_surface_default_acquire_source_image,
869     _cairo_surface_default_release_source_image,
870     NULL,  /* snapshot */
871
872     NULL, /* copy_page */
873     NULL, /* show_page */
874
875     _cairo_win32_surface_get_extents,
876     NULL, /* get_font_options */
877
878     _cairo_win32_display_surface_flush,
879     _cairo_win32_display_surface_mark_dirty,
880
881     _cairo_win32_display_surface_paint,
882     _cairo_win32_display_surface_mask,
883     _cairo_win32_display_surface_stroke,
884     _cairo_win32_display_surface_fill,
885     NULL, /* fill/stroke */
886     _cairo_win32_display_surface_glyphs,
887 };
888
889 /* Notes:
890  *
891  * Win32 alpha-understanding functions
892  *
893  * BitBlt - will copy full 32 bits from a 32bpp DIB to result
894  *          (so it's safe to use for ARGB32->ARGB32 SOURCE blits)
895  *          (but not safe going RGB24->ARGB32, if RGB24 is also represented
896  *           as a 32bpp DIB, since the alpha isn't discarded!)
897  *
898  * AlphaBlend - if both the source and dest have alpha, even if AC_SRC_ALPHA isn't set,
899  *              it will still copy over the src alpha, because the SCA value (255) will be
900  *              multiplied by all the src components.
901  */
902
903 /**
904  * cairo_win32_surface_create:
905  * @hdc: the DC to create a surface for
906  *
907  * Creates a cairo surface that targets the given DC.  The DC will be
908  * queried for its initial clip extents, and this will be used as the
909  * size of the cairo surface.  The resulting surface will always be of
910  * format %CAIRO_FORMAT_RGB24; should you need another surface format,
911  * you will need to create one through
912  * cairo_win32_surface_create_with_dib().
913  *
914  * Return value: the newly created surface
915  *
916  * Since: 1.0
917  **/
918 cairo_surface_t *
919 cairo_win32_surface_create (HDC hdc)
920 {
921     cairo_win32_display_surface_t *surface;
922
923     cairo_format_t format;
924     cairo_status_t status;
925     cairo_device_t *device;
926
927     /* Assume that everything coming in as a HDC is RGB24 */
928     format = CAIRO_FORMAT_RGB24;
929
930     surface = malloc (sizeof (*surface));
931     if (surface == NULL)
932         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
933
934     status = _cairo_win32_save_initial_clip (hdc, surface);
935     if (status) {
936         free (surface);
937         return _cairo_surface_create_in_error (status);
938     }
939
940     surface->image = NULL;
941     surface->fallback = NULL;
942     surface->win32.format = format;
943
944     surface->win32.dc = hdc;
945     surface->bitmap = NULL;
946     surface->is_dib = FALSE;
947     surface->saved_dc_bitmap = NULL;
948
949     surface->win32.flags = _cairo_win32_flags_for_dc (surface->win32.dc);
950
951     device = _cairo_win32_device_get ();
952
953     _cairo_surface_init (&surface->win32.base,
954                          &cairo_win32_display_surface_backend,
955                          device,
956                          _cairo_content_from_format (format));
957
958     cairo_device_destroy (device);
959
960     return &surface->win32.base;
961 }
962
963 /**
964  * cairo_win32_surface_create_with_dib:
965  * @format: format of pixels in the surface to create
966  * @width: width of the surface, in pixels
967  * @height: height of the surface, in pixels
968  *
969  * Creates a device-independent-bitmap surface not associated with
970  * any particular existing surface or device context. The created
971  * bitmap will be uninitialized.
972  *
973  * Return value: the newly created surface
974  *
975  * Since: 1.2
976  **/
977 cairo_surface_t *
978 cairo_win32_surface_create_with_dib (cairo_format_t format,
979                                      int            width,
980                                      int            height)
981 {
982     if (! CAIRO_FORMAT_VALID (format))
983         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
984
985     return _cairo_win32_display_surface_create_for_dc (NULL, format, width, height);
986 }
987
988 /**
989  * cairo_win32_surface_create_with_ddb:
990  * @hdc: a DC compatible with the surface to create
991  * @format: format of pixels in the surface to create
992  * @width: width of the surface, in pixels
993  * @height: height of the surface, in pixels
994  *
995  * Creates a device-dependent-bitmap surface not associated with
996  * any particular existing surface or device context. The created
997  * bitmap will be uninitialized.
998  *
999  * Return value: the newly created surface
1000  *
1001  * Since: 1.4
1002  **/
1003 cairo_surface_t *
1004 cairo_win32_surface_create_with_ddb (HDC hdc,
1005                                      cairo_format_t format,
1006                                      int width,
1007                                      int height)
1008 {
1009     cairo_win32_display_surface_t *new_surf;
1010     HBITMAP ddb;
1011     HDC screen_dc, ddb_dc;
1012     HBITMAP saved_dc_bitmap;
1013
1014     if (format != CAIRO_FORMAT_RGB24)
1015         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
1016 /* XXX handle these eventually
1017         format != CAIRO_FORMAT_A8 ||
1018         format != CAIRO_FORMAT_A1)
1019 */
1020
1021     if (!hdc) {
1022         screen_dc = GetDC (NULL);
1023         hdc = screen_dc;
1024     } else {
1025         screen_dc = NULL;
1026     }
1027
1028     ddb_dc = CreateCompatibleDC (hdc);
1029     if (ddb_dc == NULL) {
1030         new_surf = (cairo_win32_display_surface_t*) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1031         goto FINISH;
1032     }
1033
1034     ddb = CreateCompatibleBitmap (hdc, width, height);
1035     if (ddb == NULL) {
1036         DeleteDC (ddb_dc);
1037
1038         /* Note that if an app actually does hit this out of memory
1039          * condition, it's going to have lots of other issues, as
1040          * video memory is probably exhausted.  However, it can often
1041          * continue using DIBs instead of DDBs.
1042          */
1043         new_surf = (cairo_win32_display_surface_t*) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1044         goto FINISH;
1045     }
1046
1047     saved_dc_bitmap = SelectObject (ddb_dc, ddb);
1048
1049     new_surf = (cairo_win32_display_surface_t*) cairo_win32_surface_create (ddb_dc);
1050     new_surf->bitmap = ddb;
1051     new_surf->saved_dc_bitmap = saved_dc_bitmap;
1052     new_surf->is_dib = FALSE;
1053
1054 FINISH:
1055     if (screen_dc)
1056         ReleaseDC (NULL, screen_dc);
1057
1058     return &new_surf->win32.base;
1059 }