2 * DIB driver initialization and DC functions.
4 * Copyright 2011 Huw Davies
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.
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.
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
23 #include "gdi_private.h"
26 #include "wine/debug.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(dib
);
30 static void calc_shift_and_len(DWORD mask
, int *shift
, int *len
)
41 while ((mask
& 1) == 0)
47 while ((mask
& 1) == 1)
56 static void init_bit_fields(dib_info
*dib
, const DWORD
*bit_fields
)
58 dib
->red_mask
= bit_fields
[0];
59 dib
->green_mask
= bit_fields
[1];
60 dib
->blue_mask
= bit_fields
[2];
61 calc_shift_and_len(dib
->red_mask
, &dib
->red_shift
, &dib
->red_len
);
62 calc_shift_and_len(dib
->green_mask
, &dib
->green_shift
, &dib
->green_len
);
63 calc_shift_and_len(dib
->blue_mask
, &dib
->blue_shift
, &dib
->blue_len
);
66 static BOOL
init_dib_info(dib_info
*dib
, const BITMAPINFOHEADER
*bi
, const DWORD
*bit_fields
,
67 RGBQUAD
*color_table
, int color_table_size
, void *bits
)
69 static const DWORD bit_fields_888
[3] = {0xff0000, 0x00ff00, 0x0000ff};
70 static const DWORD bit_fields_555
[3] = {0x7c00, 0x03e0, 0x001f};
72 dib
->bit_count
= bi
->biBitCount
;
73 dib
->width
= bi
->biWidth
;
74 dib
->height
= bi
->biHeight
;
75 dib
->stride
= ((dib
->width
* dib
->bit_count
+ 31) >> 3) & ~3;
78 if(dib
->height
< 0) /* top-down */
80 dib
->height
= -dib
->height
;
84 /* bits always points to the top-left corner and the stride is -ve */
85 dib
->bits
= (BYTE
*)dib
->bits
+ (dib
->height
- 1) * dib
->stride
;
86 dib
->stride
= -dib
->stride
;
89 dib
->funcs
= &funcs_null
;
91 switch(dib
->bit_count
)
94 if(bi
->biCompression
== BI_RGB
)
95 bit_fields
= bit_fields_888
;
97 init_bit_fields(dib
, bit_fields
);
99 if(dib
->red_mask
== 0xff0000 && dib
->green_mask
== 0x00ff00 && dib
->blue_mask
== 0x0000ff)
100 dib
->funcs
= &funcs_8888
;
102 dib
->funcs
= &funcs_32
;
106 if(bi
->biCompression
== BI_RGB
)
107 bit_fields
= bit_fields_555
;
109 init_bit_fields(dib
, bit_fields
);
111 if(dib
->red_mask
== 0x7c00 && dib
->green_mask
== 0x03e0 && dib
->blue_mask
== 0x001f)
112 dib
->funcs
= &funcs_555
;
114 dib
->funcs
= &funcs_16
;
118 TRACE("bpp %d not supported, will forward to graphics driver.\n", dib
->bit_count
);
124 dib
->color_table
= HeapAlloc(GetProcessHeap(), 0, color_table_size
* sizeof(dib
->color_table
[0]));
125 if(!dib
->color_table
) return FALSE
;
126 dib
->color_table_size
= color_table_size
;
127 memcpy(dib
->color_table
, color_table
, color_table_size
* sizeof(color_table
[0]));
131 dib
->color_table
= NULL
;
132 dib
->color_table_size
= 0;
138 BOOL
init_dib_info_from_packed(dib_info
*dib
, const BITMAPINFOHEADER
*bi
, WORD usage
, HPALETTE palette
)
141 RGBQUAD
*color_table
= NULL
, pal_table
[256];
142 BYTE
*ptr
= (BYTE
*)bi
+ bi
->biSize
;
143 int num_colors
= bi
->biClrUsed
;
145 if(bi
->biCompression
== BI_BITFIELDS
)
147 masks
= (DWORD
*)ptr
;
148 ptr
+= 3 * sizeof(DWORD
);
151 if(!num_colors
&& bi
->biBitCount
<= 8) num_colors
= 1 << bi
->biBitCount
;
154 if(usage
== DIB_PAL_COLORS
)
156 PALETTEENTRY entries
[256];
157 const WORD
*index
= (const WORD
*) ptr
;
158 UINT i
, count
= GetPaletteEntries( palette
, 0, num_colors
, entries
);
159 for (i
= 0; i
< num_colors
; i
++, index
++)
161 PALETTEENTRY
*entry
= &entries
[*index
% count
];
162 pal_table
[i
].rgbRed
= entry
->peRed
;
163 pal_table
[i
].rgbGreen
= entry
->peGreen
;
164 pal_table
[i
].rgbBlue
= entry
->peBlue
;
165 pal_table
[i
].rgbReserved
= 0;
167 color_table
= pal_table
;
168 ptr
+= num_colors
* sizeof(WORD
);
172 color_table
= (RGBQUAD
*)ptr
;
173 ptr
+= num_colors
* sizeof(*color_table
);
177 return init_dib_info(dib
, bi
, masks
, color_table
, num_colors
, ptr
);
180 static void clear_dib_info(dib_info
*dib
)
182 dib
->color_table
= NULL
;
186 /**********************************************************************
189 * Free the resources associated with a dib and optionally the bits
191 void free_dib_info(dib_info
*dib
, BOOL free_bits
)
193 HeapFree(GetProcessHeap(), 0, dib
->color_table
);
194 dib
->color_table
= NULL
;
197 HeapFree(GetProcessHeap(), 0, dib
->bits
);
202 void copy_dib_color_info(dib_info
*dst
, const dib_info
*src
)
204 dst
->bit_count
= src
->bit_count
;
205 dst
->red_mask
= src
->red_mask
;
206 dst
->green_mask
= src
->green_mask
;
207 dst
->blue_mask
= src
->blue_mask
;
208 dst
->red_len
= src
->red_len
;
209 dst
->green_len
= src
->green_len
;
210 dst
->blue_len
= src
->blue_len
;
211 dst
->red_shift
= src
->red_shift
;
212 dst
->green_shift
= src
->green_shift
;
213 dst
->blue_shift
= src
->blue_shift
;
214 dst
->funcs
= src
->funcs
;
215 dst
->color_table_size
= src
->color_table_size
;
216 dst
->color_table
= NULL
;
217 if(dst
->color_table_size
)
219 int size
= dst
->color_table_size
* sizeof(dst
->color_table
[0]);
220 dst
->color_table
= HeapAlloc(GetProcessHeap(), 0, size
);
221 memcpy(dst
->color_table
, src
->color_table
, size
);
225 /**************************************************************
228 * Converts src into the format specified in dst.
230 * FIXME: At the moment this always creates a top-down dib,
231 * do we want to give the option of bottom-up?
233 BOOL
convert_dib(dib_info
*dst
, const dib_info
*src
)
238 dst
->height
= src
->height
;
239 dst
->width
= src
->width
;
240 dst
->stride
= ((dst
->width
* dst
->bit_count
+ 31) >> 3) & ~3;
241 dst
->bits
= HeapAlloc(GetProcessHeap(), 0, dst
->height
* dst
->stride
);
243 src_rect
.left
= src_rect
.top
= 0;
244 src_rect
.right
= src
->width
;
245 src_rect
.bottom
= src
->height
;
247 ret
= dst
->funcs
->convert_to(dst
, src
, &src_rect
);
249 if(!ret
) free_dib_info(dst
, TRUE
);
253 /***********************************************************************
256 static BOOL CDECL
dibdrv_DeleteDC( PHYSDEV dev
)
258 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
259 TRACE("(%p)\n", dev
);
260 DeleteObject(pdev
->clip
);
261 free_pattern_brush(pdev
);
262 free_dib_info(&pdev
->dib
, FALSE
);
266 /***********************************************************************
267 * dibdrv_SelectBitmap
269 static HBITMAP CDECL
dibdrv_SelectBitmap( PHYSDEV dev
, HBITMAP bitmap
)
271 PHYSDEV next
= GET_NEXT_PHYSDEV( dev
, pSelectBitmap
);
272 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
273 BITMAPOBJ
*bmp
= GDI_GetObjPtr( bitmap
, OBJ_BITMAP
);
274 TRACE("(%p, %p)\n", dev
, bitmap
);
279 pdev
->clip
= CreateRectRgn(0, 0, 0, 0);
282 clear_dib_info(&pdev
->dib
);
283 clear_dib_info(&pdev
->brush_dib
);
284 pdev
->brush_and_bits
= pdev
->brush_xor_bits
= NULL
;
286 if(!init_dib_info(&pdev
->dib
, &bmp
->dib
->dsBmih
, bmp
->dib
->dsBitfields
,
287 bmp
->color_table
, bmp
->nb_colors
, bmp
->dib
->dsBm
.bmBits
))
288 pdev
->defer
|= DEFER_FORMAT
;
290 GDI_ReleaseObj( bitmap
);
292 return next
->funcs
->pSelectBitmap( next
, bitmap
);
295 /***********************************************************************
298 static COLORREF CDECL
dibdrv_SetBkColor( PHYSDEV dev
, COLORREF color
)
300 PHYSDEV next
= GET_NEXT_PHYSDEV( dev
, pSetBkColor
);
301 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
303 pdev
->bkgnd_color
= pdev
->dib
.funcs
->colorref_to_pixel( &pdev
->dib
, color
);
305 if( GetBkMode(dev
->hdc
) == OPAQUE
)
306 calc_and_xor_masks( GetROP2(dev
->hdc
), pdev
->bkgnd_color
, &pdev
->bkgnd_and
, &pdev
->bkgnd_xor
);
309 pdev
->bkgnd_and
= ~0u;
313 return next
->funcs
->pSetBkColor( next
, color
);
316 /***********************************************************************
319 static INT CDECL
dibdrv_SetBkMode( PHYSDEV dev
, INT mode
)
321 PHYSDEV next
= GET_NEXT_PHYSDEV( dev
, pSetBkMode
);
322 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
325 calc_and_xor_masks( GetROP2(dev
->hdc
), pdev
->bkgnd_color
, &pdev
->bkgnd_and
, &pdev
->bkgnd_xor
);
328 pdev
->bkgnd_and
= ~0u;
332 return next
->funcs
->pSetBkMode( next
, mode
);
335 /***********************************************************************
336 * dibdrv_SetDeviceClipping
338 static void CDECL
dibdrv_SetDeviceClipping( PHYSDEV dev
, HRGN vis_rgn
, HRGN clip_rgn
)
340 PHYSDEV next
= GET_NEXT_PHYSDEV( dev
, pSetDeviceClipping
);
341 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
342 TRACE("(%p, %p, %p)\n", dev
, vis_rgn
, clip_rgn
);
344 CombineRgn( pdev
->clip
, vis_rgn
, clip_rgn
, clip_rgn
? RGN_AND
: RGN_COPY
);
345 return next
->funcs
->pSetDeviceClipping( next
, vis_rgn
, clip_rgn
);
348 /***********************************************************************
351 static INT CDECL
dibdrv_SetROP2( PHYSDEV dev
, INT rop
)
353 PHYSDEV next
= GET_NEXT_PHYSDEV( dev
, pSetROP2
);
354 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
356 calc_and_xor_masks(rop
, pdev
->pen_color
, &pdev
->pen_and
, &pdev
->pen_xor
);
357 update_brush_rop(pdev
, rop
);
358 if( GetBkMode(dev
->hdc
) == OPAQUE
)
359 calc_and_xor_masks(rop
, pdev
->bkgnd_color
, &pdev
->bkgnd_and
, &pdev
->bkgnd_xor
);
361 return next
->funcs
->pSetROP2( next
, rop
);
364 const DC_FUNCTIONS dib_driver
=
366 NULL
, /* pAbortDoc */
367 NULL
, /* pAbortPath */
368 NULL
, /* pAlphaBlend */
369 NULL
, /* pAngleArc */
372 NULL
, /* pBeginPath */
373 NULL
, /* pChoosePixelFormat */
375 NULL
, /* pCloseFigure */
376 NULL
, /* pCreateBitmap */
377 NULL
, /* pCreateDC */
378 NULL
, /* pCreateDIBSection */
379 NULL
, /* pDeleteBitmap */
380 dibdrv_DeleteDC
, /* pDeleteDC */
381 NULL
, /* pDeleteObject */
382 NULL
, /* pDescribePixelFormat */
383 NULL
, /* pDeviceCapabilities */
388 NULL
, /* pEnumDeviceFonts */
389 NULL
, /* pEnumICMProfiles */
390 NULL
, /* pExcludeClipRect */
391 NULL
, /* pExtDeviceMode */
392 NULL
, /* pExtEscape */
393 NULL
, /* pExtFloodFill */
394 NULL
, /* pExtSelectClipRgn */
395 NULL
, /* pExtTextOut */
396 NULL
, /* pFillPath */
398 NULL
, /* pFlattenPath */
399 NULL
, /* pFrameRgn */
400 NULL
, /* pGdiComment */
401 NULL
, /* pGetBitmapBits */
402 NULL
, /* pGetCharWidth */
403 NULL
, /* pGetDIBits */
404 NULL
, /* pGetDeviceCaps */
405 NULL
, /* pGetDeviceGammaRamp */
406 NULL
, /* pGetICMProfile */
407 NULL
, /* pGetNearestColor */
408 NULL
, /* pGetPixel */
409 NULL
, /* pGetPixelFormat */
410 NULL
, /* pGetSystemPaletteEntries */
411 NULL
, /* pGetTextExtentExPoint */
412 NULL
, /* pGetTextMetrics */
413 NULL
, /* pIntersectClipRect */
414 NULL
, /* pInvertRgn */
415 dibdrv_LineTo
, /* pLineTo */
416 NULL
, /* pModifyWorldTransform */
418 NULL
, /* pOffsetClipRgn */
419 NULL
, /* pOffsetViewportOrg */
420 NULL
, /* pOffsetWindowOrg */
421 dibdrv_PaintRgn
, /* pPaintRgn */
422 dibdrv_PatBlt
, /* pPatBlt */
424 NULL
, /* pPolyBezier */
425 NULL
, /* pPolyBezierTo */
426 NULL
, /* pPolyDraw */
427 NULL
, /* pPolyPolygon */
428 NULL
, /* pPolyPolyline */
430 NULL
, /* pPolyline */
431 NULL
, /* pPolylineTo */
432 NULL
, /* pRealizeDefaultPalette */
433 NULL
, /* pRealizePalette */
434 dibdrv_Rectangle
, /* pRectangle */
436 NULL
, /* pRestoreDC */
437 NULL
, /* pRoundRect */
439 NULL
, /* pScaleViewportExt */
440 NULL
, /* pScaleWindowExt */
441 dibdrv_SelectBitmap
, /* pSelectBitmap */
442 dibdrv_SelectBrush
, /* pSelectBrush */
443 NULL
, /* pSelectClipPath */
444 NULL
, /* pSelectFont */
445 NULL
, /* pSelectPalette */
446 dibdrv_SelectPen
, /* pSelectPen */
447 NULL
, /* pSetArcDirection */
448 NULL
, /* pSetBitmapBits */
449 dibdrv_SetBkColor
, /* pSetBkColor */
450 dibdrv_SetBkMode
, /* pSetBkMode */
451 dibdrv_SetDCBrushColor
, /* pSetDCBrushColor */
452 dibdrv_SetDCPenColor
, /* pSetDCPenColor */
453 NULL
, /* pSetDIBColorTable */
454 NULL
, /* pSetDIBits */
455 NULL
, /* pSetDIBitsToDevice */
456 dibdrv_SetDeviceClipping
, /* pSetDeviceClipping */
457 NULL
, /* pSetDeviceGammaRamp */
458 NULL
, /* pSetLayout */
459 NULL
, /* pSetMapMode */
460 NULL
, /* pSetMapperFlags */
461 NULL
, /* pSetPixel */
462 NULL
, /* pSetPixelFormat */
463 NULL
, /* pSetPolyFillMode */
464 dibdrv_SetROP2
, /* pSetROP2 */
465 NULL
, /* pSetRelAbs */
466 NULL
, /* pSetStretchBltMode */
467 NULL
, /* pSetTextAlign */
468 NULL
, /* pSetTextCharacterExtra */
469 NULL
, /* pSetTextColor */
470 NULL
, /* pSetTextJustification */
471 NULL
, /* pSetViewportExt */
472 NULL
, /* pSetViewportOrg */
473 NULL
, /* pSetWindowExt */
474 NULL
, /* pSetWindowOrg */
475 NULL
, /* pSetWorldTransform */
476 NULL
, /* pStartDoc */
477 NULL
, /* pStartPage */
478 NULL
, /* pStretchBlt */
479 NULL
, /* pStretchDIBits */
480 NULL
, /* pStrokeAndFillPath */
481 NULL
, /* pStrokePath */
482 NULL
, /* pSwapBuffers */
483 NULL
, /* pUnrealizePalette */
484 NULL
, /* pWidenPath */
485 NULL
, /* pwglCopyContext */
486 NULL
, /* pwglCreateContext */
487 NULL
, /* pwglCreateContextAttribsARB */
488 NULL
, /* pwglDeleteContext */
489 NULL
, /* pwglGetProcAddress */
490 NULL
, /* pwglGetPbufferDCARB */
491 NULL
, /* pwglMakeCurrent */
492 NULL
, /* pwglMakeContextCurrentARB */
493 NULL
, /* pwglSetPixelFormatWINE */
494 NULL
, /* pwglShareLists */
495 NULL
, /* pwglUseFontBitmapsA */
496 NULL
/* pwglUseFontBitmapsW */