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 dib
->funcs
= &funcs_24
;
110 if(bi
->biCompression
== BI_RGB
)
111 bit_fields
= bit_fields_555
;
113 init_bit_fields(dib
, bit_fields
);
115 if(dib
->red_mask
== 0x7c00 && dib
->green_mask
== 0x03e0 && dib
->blue_mask
== 0x001f)
116 dib
->funcs
= &funcs_555
;
118 dib
->funcs
= &funcs_16
;
122 dib
->funcs
= &funcs_8
;
126 dib
->funcs
= &funcs_4
;
130 TRACE("bpp %d not supported, will forward to graphics driver.\n", dib
->bit_count
);
136 dib
->color_table
= HeapAlloc(GetProcessHeap(), 0, color_table_size
* sizeof(dib
->color_table
[0]));
137 if(!dib
->color_table
) return FALSE
;
138 dib
->color_table_size
= color_table_size
;
139 memcpy(dib
->color_table
, color_table
, color_table_size
* sizeof(color_table
[0]));
143 dib
->color_table
= NULL
;
144 dib
->color_table_size
= 0;
150 BOOL
init_dib_info_from_packed(dib_info
*dib
, const BITMAPINFOHEADER
*bi
, WORD usage
, HPALETTE palette
)
153 RGBQUAD
*color_table
= NULL
, pal_table
[256];
154 BYTE
*ptr
= (BYTE
*)bi
+ bi
->biSize
;
155 int num_colors
= bi
->biClrUsed
;
157 if(bi
->biCompression
== BI_BITFIELDS
)
159 masks
= (DWORD
*)ptr
;
160 ptr
+= 3 * sizeof(DWORD
);
163 if(!num_colors
&& bi
->biBitCount
<= 8) num_colors
= 1 << bi
->biBitCount
;
166 if(usage
== DIB_PAL_COLORS
)
168 PALETTEENTRY entries
[256];
169 const WORD
*index
= (const WORD
*) ptr
;
170 UINT i
, count
= GetPaletteEntries( palette
, 0, num_colors
, entries
);
171 for (i
= 0; i
< num_colors
; i
++, index
++)
173 PALETTEENTRY
*entry
= &entries
[*index
% count
];
174 pal_table
[i
].rgbRed
= entry
->peRed
;
175 pal_table
[i
].rgbGreen
= entry
->peGreen
;
176 pal_table
[i
].rgbBlue
= entry
->peBlue
;
177 pal_table
[i
].rgbReserved
= 0;
179 color_table
= pal_table
;
180 ptr
+= num_colors
* sizeof(WORD
);
184 color_table
= (RGBQUAD
*)ptr
;
185 ptr
+= num_colors
* sizeof(*color_table
);
189 return init_dib_info(dib
, bi
, masks
, color_table
, num_colors
, ptr
);
192 static void clear_dib_info(dib_info
*dib
)
194 dib
->color_table
= NULL
;
198 /**********************************************************************
201 * Free the resources associated with a dib and optionally the bits
203 void free_dib_info(dib_info
*dib
, BOOL free_bits
)
205 HeapFree(GetProcessHeap(), 0, dib
->color_table
);
206 dib
->color_table
= NULL
;
209 HeapFree(GetProcessHeap(), 0, dib
->bits
);
214 void copy_dib_color_info(dib_info
*dst
, const dib_info
*src
)
216 dst
->bit_count
= src
->bit_count
;
217 dst
->red_mask
= src
->red_mask
;
218 dst
->green_mask
= src
->green_mask
;
219 dst
->blue_mask
= src
->blue_mask
;
220 dst
->red_len
= src
->red_len
;
221 dst
->green_len
= src
->green_len
;
222 dst
->blue_len
= src
->blue_len
;
223 dst
->red_shift
= src
->red_shift
;
224 dst
->green_shift
= src
->green_shift
;
225 dst
->blue_shift
= src
->blue_shift
;
226 dst
->funcs
= src
->funcs
;
227 dst
->color_table_size
= src
->color_table_size
;
228 dst
->color_table
= NULL
;
229 if(dst
->color_table_size
)
231 int size
= dst
->color_table_size
* sizeof(dst
->color_table
[0]);
232 dst
->color_table
= HeapAlloc(GetProcessHeap(), 0, size
);
233 memcpy(dst
->color_table
, src
->color_table
, size
);
237 /**************************************************************
240 * Converts src into the format specified in dst.
242 * FIXME: At the moment this always creates a top-down dib,
243 * do we want to give the option of bottom-up?
245 BOOL
convert_dib(dib_info
*dst
, const dib_info
*src
)
250 dst
->height
= src
->height
;
251 dst
->width
= src
->width
;
252 dst
->stride
= ((dst
->width
* dst
->bit_count
+ 31) >> 3) & ~3;
253 dst
->bits
= HeapAlloc(GetProcessHeap(), 0, dst
->height
* dst
->stride
);
255 src_rect
.left
= src_rect
.top
= 0;
256 src_rect
.right
= src
->width
;
257 src_rect
.bottom
= src
->height
;
259 ret
= dst
->funcs
->convert_to(dst
, src
, &src_rect
);
261 if(!ret
) free_dib_info(dst
, TRUE
);
265 /***********************************************************************
268 static BOOL CDECL
dibdrv_DeleteDC( PHYSDEV dev
)
270 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
271 TRACE("(%p)\n", dev
);
272 DeleteObject(pdev
->clip
);
273 free_pattern_brush(pdev
);
274 free_dib_info(&pdev
->dib
, FALSE
);
278 /***********************************************************************
279 * dibdrv_SelectBitmap
281 static HBITMAP CDECL
dibdrv_SelectBitmap( PHYSDEV dev
, HBITMAP bitmap
)
283 PHYSDEV next
= GET_NEXT_PHYSDEV( dev
, pSelectBitmap
);
284 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
285 BITMAPOBJ
*bmp
= GDI_GetObjPtr( bitmap
, OBJ_BITMAP
);
286 TRACE("(%p, %p)\n", dev
, bitmap
);
291 pdev
->clip
= CreateRectRgn(0, 0, 0, 0);
294 clear_dib_info(&pdev
->dib
);
295 clear_dib_info(&pdev
->brush_dib
);
296 pdev
->brush_and_bits
= pdev
->brush_xor_bits
= NULL
;
298 if(!init_dib_info(&pdev
->dib
, &bmp
->dib
->dsBmih
, bmp
->dib
->dsBitfields
,
299 bmp
->color_table
, bmp
->nb_colors
, bmp
->dib
->dsBm
.bmBits
))
300 pdev
->defer
|= DEFER_FORMAT
;
302 GDI_ReleaseObj( bitmap
);
304 return next
->funcs
->pSelectBitmap( next
, bitmap
);
307 /***********************************************************************
310 static COLORREF CDECL
dibdrv_SetBkColor( PHYSDEV dev
, COLORREF color
)
312 PHYSDEV next
= GET_NEXT_PHYSDEV( dev
, pSetBkColor
);
313 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
315 pdev
->bkgnd_color
= pdev
->dib
.funcs
->colorref_to_pixel( &pdev
->dib
, color
);
317 if( GetBkMode(dev
->hdc
) == OPAQUE
)
318 calc_and_xor_masks( GetROP2(dev
->hdc
), pdev
->bkgnd_color
, &pdev
->bkgnd_and
, &pdev
->bkgnd_xor
);
321 pdev
->bkgnd_and
= ~0u;
325 return next
->funcs
->pSetBkColor( next
, color
);
328 /***********************************************************************
331 static INT CDECL
dibdrv_SetBkMode( PHYSDEV dev
, INT mode
)
333 PHYSDEV next
= GET_NEXT_PHYSDEV( dev
, pSetBkMode
);
334 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
337 calc_and_xor_masks( GetROP2(dev
->hdc
), pdev
->bkgnd_color
, &pdev
->bkgnd_and
, &pdev
->bkgnd_xor
);
340 pdev
->bkgnd_and
= ~0u;
344 return next
->funcs
->pSetBkMode( next
, mode
);
347 /***********************************************************************
348 * dibdrv_SetDeviceClipping
350 static void CDECL
dibdrv_SetDeviceClipping( PHYSDEV dev
, HRGN vis_rgn
, HRGN clip_rgn
)
352 PHYSDEV next
= GET_NEXT_PHYSDEV( dev
, pSetDeviceClipping
);
353 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
354 TRACE("(%p, %p, %p)\n", dev
, vis_rgn
, clip_rgn
);
356 CombineRgn( pdev
->clip
, vis_rgn
, clip_rgn
, clip_rgn
? RGN_AND
: RGN_COPY
);
357 return next
->funcs
->pSetDeviceClipping( next
, vis_rgn
, clip_rgn
);
360 static void update_masks( dibdrv_physdev
*pdev
, INT rop
)
362 calc_and_xor_masks( rop
, pdev
->pen_color
, &pdev
->pen_and
, &pdev
->pen_xor
);
363 update_brush_rop( pdev
, rop
);
364 if( GetBkMode( pdev
->dev
.hdc
) == OPAQUE
)
365 calc_and_xor_masks( rop
, pdev
->bkgnd_color
, &pdev
->bkgnd_and
, &pdev
->bkgnd_xor
);
368 /***********************************************************************
369 * dibdrv_SetDIBColorTable
371 static UINT CDECL
dibdrv_SetDIBColorTable( PHYSDEV dev
, UINT pos
, UINT count
, const RGBQUAD
*colors
)
373 PHYSDEV next
= GET_NEXT_PHYSDEV( dev
, pSetDIBColorTable
);
374 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
375 TRACE("(%p, %d, %d, %p)\n", dev
, pos
, count
, colors
);
377 if( pdev
->dib
.color_table
&& pos
< pdev
->dib
.color_table_size
)
379 if( pos
+ count
> pdev
->dib
.color_table_size
) count
= pdev
->dib
.color_table_size
- pos
;
380 memcpy( pdev
->dib
.color_table
+ pos
, colors
, count
* sizeof(RGBQUAD
) );
382 pdev
->pen_color
= pdev
->dib
.funcs
->colorref_to_pixel( &pdev
->dib
, pdev
->pen_colorref
);
383 pdev
->brush_color
= pdev
->dib
.funcs
->colorref_to_pixel( &pdev
->dib
, pdev
->brush_colorref
);
384 pdev
->bkgnd_color
= pdev
->dib
.funcs
->colorref_to_pixel( &pdev
->dib
, GetBkColor( dev
->hdc
) );
386 update_masks( pdev
, GetROP2( dev
->hdc
) );
388 return next
->funcs
->pSetDIBColorTable( next
, pos
, count
, colors
);
391 /***********************************************************************
394 static INT CDECL
dibdrv_SetROP2( PHYSDEV dev
, INT rop
)
396 PHYSDEV next
= GET_NEXT_PHYSDEV( dev
, pSetROP2
);
397 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
399 update_masks( pdev
, rop
);
401 return next
->funcs
->pSetROP2( next
, rop
);
404 const DC_FUNCTIONS dib_driver
=
406 NULL
, /* pAbortDoc */
407 NULL
, /* pAbortPath */
408 NULL
, /* pAlphaBlend */
409 NULL
, /* pAngleArc */
412 NULL
, /* pBeginPath */
413 NULL
, /* pChoosePixelFormat */
415 NULL
, /* pCloseFigure */
416 NULL
, /* pCreateBitmap */
417 NULL
, /* pCreateDC */
418 NULL
, /* pCreateDIBSection */
419 NULL
, /* pDeleteBitmap */
420 dibdrv_DeleteDC
, /* pDeleteDC */
421 NULL
, /* pDeleteObject */
422 NULL
, /* pDescribePixelFormat */
423 NULL
, /* pDeviceCapabilities */
428 NULL
, /* pEnumDeviceFonts */
429 NULL
, /* pEnumICMProfiles */
430 NULL
, /* pExcludeClipRect */
431 NULL
, /* pExtDeviceMode */
432 NULL
, /* pExtEscape */
433 NULL
, /* pExtFloodFill */
434 NULL
, /* pExtSelectClipRgn */
435 NULL
, /* pExtTextOut */
436 NULL
, /* pFillPath */
438 NULL
, /* pFlattenPath */
439 NULL
, /* pFrameRgn */
440 NULL
, /* pGdiComment */
441 NULL
, /* pGetBitmapBits */
442 NULL
, /* pGetCharWidth */
443 NULL
, /* pGetDIBits */
444 NULL
, /* pGetDeviceCaps */
445 NULL
, /* pGetDeviceGammaRamp */
446 NULL
, /* pGetICMProfile */
447 NULL
, /* pGetNearestColor */
448 NULL
, /* pGetPixel */
449 NULL
, /* pGetPixelFormat */
450 NULL
, /* pGetSystemPaletteEntries */
451 NULL
, /* pGetTextExtentExPoint */
452 NULL
, /* pGetTextMetrics */
453 NULL
, /* pIntersectClipRect */
454 NULL
, /* pInvertRgn */
455 dibdrv_LineTo
, /* pLineTo */
456 NULL
, /* pModifyWorldTransform */
458 NULL
, /* pOffsetClipRgn */
459 NULL
, /* pOffsetViewportOrg */
460 NULL
, /* pOffsetWindowOrg */
461 dibdrv_PaintRgn
, /* pPaintRgn */
462 dibdrv_PatBlt
, /* pPatBlt */
464 NULL
, /* pPolyBezier */
465 NULL
, /* pPolyBezierTo */
466 NULL
, /* pPolyDraw */
467 NULL
, /* pPolyPolygon */
468 NULL
, /* pPolyPolyline */
470 NULL
, /* pPolyline */
471 NULL
, /* pPolylineTo */
472 NULL
, /* pRealizeDefaultPalette */
473 NULL
, /* pRealizePalette */
474 dibdrv_Rectangle
, /* pRectangle */
476 NULL
, /* pRestoreDC */
477 NULL
, /* pRoundRect */
479 NULL
, /* pScaleViewportExt */
480 NULL
, /* pScaleWindowExt */
481 dibdrv_SelectBitmap
, /* pSelectBitmap */
482 dibdrv_SelectBrush
, /* pSelectBrush */
483 NULL
, /* pSelectClipPath */
484 NULL
, /* pSelectFont */
485 NULL
, /* pSelectPalette */
486 dibdrv_SelectPen
, /* pSelectPen */
487 NULL
, /* pSetArcDirection */
488 NULL
, /* pSetBitmapBits */
489 dibdrv_SetBkColor
, /* pSetBkColor */
490 dibdrv_SetBkMode
, /* pSetBkMode */
491 dibdrv_SetDCBrushColor
, /* pSetDCBrushColor */
492 dibdrv_SetDCPenColor
, /* pSetDCPenColor */
493 dibdrv_SetDIBColorTable
, /* pSetDIBColorTable */
494 NULL
, /* pSetDIBits */
495 NULL
, /* pSetDIBitsToDevice */
496 dibdrv_SetDeviceClipping
, /* pSetDeviceClipping */
497 NULL
, /* pSetDeviceGammaRamp */
498 NULL
, /* pSetLayout */
499 NULL
, /* pSetMapMode */
500 NULL
, /* pSetMapperFlags */
501 NULL
, /* pSetPixel */
502 NULL
, /* pSetPixelFormat */
503 NULL
, /* pSetPolyFillMode */
504 dibdrv_SetROP2
, /* pSetROP2 */
505 NULL
, /* pSetRelAbs */
506 NULL
, /* pSetStretchBltMode */
507 NULL
, /* pSetTextAlign */
508 NULL
, /* pSetTextCharacterExtra */
509 NULL
, /* pSetTextColor */
510 NULL
, /* pSetTextJustification */
511 NULL
, /* pSetViewportExt */
512 NULL
, /* pSetViewportOrg */
513 NULL
, /* pSetWindowExt */
514 NULL
, /* pSetWindowOrg */
515 NULL
, /* pSetWorldTransform */
516 NULL
, /* pStartDoc */
517 NULL
, /* pStartPage */
518 NULL
, /* pStretchBlt */
519 NULL
, /* pStretchDIBits */
520 NULL
, /* pStrokeAndFillPath */
521 NULL
, /* pStrokePath */
522 NULL
, /* pSwapBuffers */
523 NULL
, /* pUnrealizePalette */
524 NULL
, /* pWidenPath */
525 NULL
, /* pwglCopyContext */
526 NULL
, /* pwglCreateContext */
527 NULL
, /* pwglCreateContextAttribsARB */
528 NULL
, /* pwglDeleteContext */
529 NULL
, /* pwglGetProcAddress */
530 NULL
, /* pwglGetPbufferDCARB */
531 NULL
, /* pwglMakeCurrent */
532 NULL
, /* pwglMakeContextCurrentARB */
533 NULL
, /* pwglSetPixelFormatWINE */
534 NULL
, /* pwglShareLists */
535 NULL
, /* pwglUseFontBitmapsA */
536 NULL
/* pwglUseFontBitmapsW */