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/exception.h"
27 #include "wine/debug.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(dib
);
31 static const DWORD bit_fields_888
[3] = {0xff0000, 0x00ff00, 0x0000ff};
32 static const DWORD bit_fields_555
[3] = {0x7c00, 0x03e0, 0x001f};
34 static void calc_shift_and_len(DWORD mask
, int *shift
, int *len
)
45 while ((mask
& 1) == 0)
51 while ((mask
& 1) == 1)
60 static void init_bit_fields(dib_info
*dib
, const DWORD
*bit_fields
)
62 dib
->red_mask
= bit_fields
[0];
63 dib
->green_mask
= bit_fields
[1];
64 dib
->blue_mask
= bit_fields
[2];
65 calc_shift_and_len(dib
->red_mask
, &dib
->red_shift
, &dib
->red_len
);
66 calc_shift_and_len(dib
->green_mask
, &dib
->green_shift
, &dib
->green_len
);
67 calc_shift_and_len(dib
->blue_mask
, &dib
->blue_shift
, &dib
->blue_len
);
70 BOOL
init_dib_info(dib_info
*dib
, const BITMAPINFOHEADER
*bi
, const DWORD
*bit_fields
,
71 RGBQUAD
*color_table
, int color_table_size
, void *bits
, enum dib_info_flags flags
)
73 dib
->bit_count
= bi
->biBitCount
;
74 dib
->width
= bi
->biWidth
;
75 dib
->height
= bi
->biHeight
;
76 dib
->stride
= get_dib_stride( dib
->width
, dib
->bit_count
);
78 dib
->bits
.is_copy
= FALSE
;
79 dib
->bits
.free
= NULL
;
80 dib
->bits
.param
= NULL
;
83 if(dib
->height
< 0) /* top-down */
85 dib
->height
= -dib
->height
;
89 /* bits always points to the top-left corner and the stride is -ve */
90 dib
->bits
.ptr
= (BYTE
*)dib
->bits
.ptr
+ (dib
->height
- 1) * dib
->stride
;
91 dib
->stride
= -dib
->stride
;
94 dib
->funcs
= &funcs_null
;
96 switch(dib
->bit_count
)
99 if(bi
->biCompression
== BI_RGB
)
100 bit_fields
= bit_fields_888
;
102 init_bit_fields(dib
, bit_fields
);
104 if(dib
->red_mask
== 0xff0000 && dib
->green_mask
== 0x00ff00 && dib
->blue_mask
== 0x0000ff)
105 dib
->funcs
= &funcs_8888
;
107 dib
->funcs
= &funcs_32
;
111 dib
->funcs
= &funcs_24
;
115 if(bi
->biCompression
== BI_RGB
)
116 bit_fields
= bit_fields_555
;
118 init_bit_fields(dib
, bit_fields
);
120 if(dib
->red_mask
== 0x7c00 && dib
->green_mask
== 0x03e0 && dib
->blue_mask
== 0x001f)
121 dib
->funcs
= &funcs_555
;
123 dib
->funcs
= &funcs_16
;
127 dib
->funcs
= &funcs_8
;
131 dib
->funcs
= &funcs_4
;
135 dib
->funcs
= &funcs_1
;
139 TRACE("bpp %d not supported, will forward to graphics driver.\n", dib
->bit_count
);
145 if (flags
& private_color_table
)
147 dib
->color_table
= HeapAlloc(GetProcessHeap(), 0, color_table_size
* sizeof(dib
->color_table
[0]));
148 if(!dib
->color_table
) return FALSE
;
149 memcpy(dib
->color_table
, color_table
, color_table_size
* sizeof(color_table
[0]));
152 dib
->color_table
= color_table
;
153 dib
->color_table_size
= color_table_size
;
157 dib
->color_table
= NULL
;
158 dib
->color_table_size
= 0;
164 BOOL
init_dib_info_from_packed(dib_info
*dib
, const BITMAPINFOHEADER
*bi
, WORD usage
, HPALETTE palette
)
167 RGBQUAD
*color_table
= NULL
, pal_table
[256];
168 BYTE
*ptr
= (BYTE
*)bi
+ bi
->biSize
;
169 int num_colors
= get_dib_num_of_colors( (const BITMAPINFO
*)bi
);
171 if(bi
->biCompression
== BI_BITFIELDS
)
173 masks
= (DWORD
*)ptr
;
174 ptr
+= 3 * sizeof(DWORD
);
179 if(usage
== DIB_PAL_COLORS
)
181 PALETTEENTRY entries
[256];
182 const WORD
*index
= (const WORD
*) ptr
;
183 UINT i
, count
= GetPaletteEntries( palette
, 0, num_colors
, entries
);
184 for (i
= 0; i
< num_colors
; i
++, index
++)
186 PALETTEENTRY
*entry
= &entries
[*index
% count
];
187 pal_table
[i
].rgbRed
= entry
->peRed
;
188 pal_table
[i
].rgbGreen
= entry
->peGreen
;
189 pal_table
[i
].rgbBlue
= entry
->peBlue
;
190 pal_table
[i
].rgbReserved
= 0;
192 color_table
= pal_table
;
193 ptr
+= num_colors
* sizeof(WORD
);
197 color_table
= (RGBQUAD
*)ptr
;
198 ptr
+= num_colors
* sizeof(*color_table
);
202 return init_dib_info(dib
, bi
, masks
, color_table
, num_colors
, ptr
, private_color_table
);
205 BOOL
init_dib_info_from_bitmapinfo(dib_info
*dib
, const BITMAPINFO
*info
, void *bits
, enum dib_info_flags flags
)
207 unsigned int colors
= get_dib_num_of_colors( info
);
208 void *colorptr
= (char *)&info
->bmiHeader
+ info
->bmiHeader
.biSize
;
209 const DWORD
*bitfields
= (info
->bmiHeader
.biCompression
== BI_BITFIELDS
) ? (DWORD
*)colorptr
: NULL
;
211 return init_dib_info( dib
, &info
->bmiHeader
, bitfields
, colors
? colorptr
: NULL
, colors
, bits
, flags
);
214 BOOL
init_dib_info_from_bitmapobj(dib_info
*dib
, BITMAPOBJ
*bmp
, enum dib_info_flags flags
)
218 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
219 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
221 get_ddb_bitmapinfo( bmp
, info
);
222 return init_dib_info_from_bitmapinfo( dib
, info
, bmp
->bitmap
.bmBits
,
223 flags
| private_color_table
);
225 return init_dib_info( dib
, &bmp
->dib
->dsBmih
, bmp
->dib
->dsBitfields
,
226 bmp
->color_table
, bmp
->nb_colors
, bmp
->dib
->dsBm
.bmBits
, flags
);
229 static void clear_dib_info(dib_info
*dib
)
231 dib
->color_table
= NULL
;
232 dib
->bits
.ptr
= NULL
;
233 dib
->bits
.free
= NULL
;
234 dib
->bits
.param
= NULL
;
237 /**********************************************************************
240 * Free the resources associated with a dib and optionally the bits
242 void free_dib_info(dib_info
*dib
)
244 if (dib
->flags
& private_color_table
)
245 HeapFree(GetProcessHeap(), 0, dib
->color_table
);
247 if (dib
->bits
.free
) dib
->bits
.free( &dib
->bits
);
248 clear_dib_info( dib
);
251 void copy_dib_color_info(dib_info
*dst
, const dib_info
*src
)
253 dst
->bit_count
= src
->bit_count
;
254 dst
->red_mask
= src
->red_mask
;
255 dst
->green_mask
= src
->green_mask
;
256 dst
->blue_mask
= src
->blue_mask
;
257 dst
->red_len
= src
->red_len
;
258 dst
->green_len
= src
->green_len
;
259 dst
->blue_len
= src
->blue_len
;
260 dst
->red_shift
= src
->red_shift
;
261 dst
->green_shift
= src
->green_shift
;
262 dst
->blue_shift
= src
->blue_shift
;
263 dst
->funcs
= src
->funcs
;
264 dst
->color_table_size
= src
->color_table_size
;
265 dst
->color_table
= NULL
;
266 dst
->flags
= src
->flags
;
267 if(dst
->color_table_size
)
269 int size
= dst
->color_table_size
* sizeof(dst
->color_table
[0]);
270 if (dst
->flags
& private_color_table
)
272 dst
->color_table
= HeapAlloc(GetProcessHeap(), 0, size
);
273 memcpy(dst
->color_table
, src
->color_table
, size
);
276 dst
->color_table
= src
->color_table
;
280 DWORD
convert_bitmapinfo( const BITMAPINFO
*src_info
, void *src_bits
, struct bitblt_coords
*src
,
281 const BITMAPINFO
*dst_info
, void *dst_bits
)
283 dib_info src_dib
, dst_dib
;
286 if ( !init_dib_info_from_bitmapinfo( &src_dib
, src_info
, src_bits
, 0 ) )
287 return ERROR_BAD_FORMAT
;
288 if ( !init_dib_info_from_bitmapinfo( &dst_dib
, dst_info
, dst_bits
, 0 ) )
289 return ERROR_BAD_FORMAT
;
293 ret
= dst_dib
.funcs
->convert_to( &dst_dib
, &src_dib
, &src
->visrect
);
297 WARN( "invalid bits pointer %p\n", src_bits
);
302 /* We shared the color tables, so there's no need to free the dib_infos here */
303 if(!ret
) return ERROR_BAD_FORMAT
;
305 /* update coordinates, the destination rectangle is always stored at 0,0 */
306 src
->x
-= src
->visrect
.left
;
307 src
->y
-= src
->visrect
.top
;
308 offset_rect( &src
->visrect
, -src
->visrect
.left
, -src
->visrect
.top
);
309 return ERROR_SUCCESS
;
312 static void update_fg_colors( dibdrv_physdev
*pdev
)
314 pdev
->pen_color
= get_fg_color( pdev
, pdev
->pen_colorref
);
315 pdev
->brush_color
= get_fg_color( pdev
, pdev
->brush_colorref
);
318 static void update_masks( dibdrv_physdev
*pdev
, INT rop
)
320 calc_and_xor_masks( rop
, pdev
->pen_color
, &pdev
->pen_and
, &pdev
->pen_xor
);
321 update_brush_rop( pdev
, rop
);
322 if( GetBkMode( pdev
->dev
.hdc
) == OPAQUE
)
323 calc_and_xor_masks( rop
, pdev
->bkgnd_color
, &pdev
->bkgnd_and
, &pdev
->bkgnd_xor
);
326 /***********************************************************************
327 * add_extra_clipping_region
329 * Temporarily add a region to the current clipping region.
330 * The returned region must be restored with restore_clipping_region.
332 HRGN
add_extra_clipping_region( dibdrv_physdev
*pdev
, HRGN rgn
)
336 if (!(clip
= CreateRectRgn( 0, 0, 0, 0 ))) return 0;
337 CombineRgn( clip
, pdev
->clip
, rgn
, RGN_AND
);
343 /***********************************************************************
344 * restore_clipping_region
346 void restore_clipping_region( dibdrv_physdev
*pdev
, HRGN rgn
)
349 DeleteObject( pdev
->clip
);
353 /**********************************************************************
356 static BOOL
dibdrv_CreateDC( PHYSDEV
*dev
, LPCWSTR driver
, LPCWSTR device
,
357 LPCWSTR output
, const DEVMODEW
*data
)
359 dibdrv_physdev
*pdev
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pdev
) );
361 if (!pdev
) return FALSE
;
362 if (!(pdev
->clip
= CreateRectRgn(0, 0, 0, 0)))
364 HeapFree( GetProcessHeap(), 0, pdev
);
367 clear_dib_info(&pdev
->dib
);
368 clear_dib_info(&pdev
->brush_dib
);
369 push_dc_driver( dev
, &pdev
->dev
, &dib_driver
);
373 /***********************************************************************
376 static BOOL
dibdrv_DeleteDC( PHYSDEV dev
)
378 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
379 TRACE("(%p)\n", dev
);
380 DeleteObject(pdev
->clip
);
381 free_pattern_brush(pdev
);
382 free_dib_info(&pdev
->dib
);
383 HeapFree( GetProcessHeap(), 0, pdev
);
387 /***********************************************************************
388 * dibdrv_SelectBitmap
390 static HBITMAP
dibdrv_SelectBitmap( PHYSDEV dev
, HBITMAP bitmap
)
392 PHYSDEV next
= GET_NEXT_PHYSDEV( dev
, pSelectBitmap
);
393 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
394 BITMAPOBJ
*bmp
= GDI_GetObjPtr( bitmap
, OBJ_BITMAP
);
395 TRACE("(%p, %p)\n", dev
, bitmap
);
400 free_dib_info(&pdev
->dib
);
402 if(!init_dib_info_from_bitmapobj(&pdev
->dib
, bmp
, private_color_table
))
403 pdev
->defer
|= DEFER_FORMAT
;
405 GDI_ReleaseObj( bitmap
);
407 return next
->funcs
->pSelectBitmap( next
, bitmap
);
410 /***********************************************************************
413 static COLORREF
dibdrv_SetBkColor( PHYSDEV dev
, COLORREF color
)
415 PHYSDEV next
= GET_NEXT_PHYSDEV( dev
, pSetBkColor
);
416 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
418 pdev
->bkgnd_color
= pdev
->dib
.funcs
->colorref_to_pixel( &pdev
->dib
, color
);
420 if( GetBkMode(dev
->hdc
) == OPAQUE
)
421 calc_and_xor_masks( GetROP2(dev
->hdc
), pdev
->bkgnd_color
, &pdev
->bkgnd_and
, &pdev
->bkgnd_xor
);
424 pdev
->bkgnd_and
= ~0u;
428 update_fg_colors( pdev
); /* Only needed in the 1 bpp case */
430 return next
->funcs
->pSetBkColor( next
, color
);
433 /***********************************************************************
436 static INT
dibdrv_SetBkMode( PHYSDEV dev
, INT mode
)
438 PHYSDEV next
= GET_NEXT_PHYSDEV( dev
, pSetBkMode
);
439 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
442 calc_and_xor_masks( GetROP2(dev
->hdc
), pdev
->bkgnd_color
, &pdev
->bkgnd_and
, &pdev
->bkgnd_xor
);
445 pdev
->bkgnd_and
= ~0u;
449 return next
->funcs
->pSetBkMode( next
, mode
);
452 /***********************************************************************
453 * dibdrv_SetDeviceClipping
455 static void dibdrv_SetDeviceClipping( PHYSDEV dev
, HRGN vis_rgn
, HRGN clip_rgn
)
457 PHYSDEV next
= GET_NEXT_PHYSDEV( dev
, pSetDeviceClipping
);
458 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
459 TRACE("(%p, %p, %p)\n", dev
, vis_rgn
, clip_rgn
);
461 CombineRgn( pdev
->clip
, vis_rgn
, clip_rgn
, clip_rgn
? RGN_AND
: RGN_COPY
);
462 return next
->funcs
->pSetDeviceClipping( next
, vis_rgn
, clip_rgn
);
465 /***********************************************************************
466 * dibdrv_SetDIBColorTable
468 static UINT
dibdrv_SetDIBColorTable( PHYSDEV dev
, UINT pos
, UINT count
, const RGBQUAD
*colors
)
470 PHYSDEV next
= GET_NEXT_PHYSDEV( dev
, pSetDIBColorTable
);
471 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
472 TRACE("(%p, %d, %d, %p)\n", dev
, pos
, count
, colors
);
474 if( pdev
->dib
.color_table
&& pos
< pdev
->dib
.color_table_size
)
476 if( pos
+ count
> pdev
->dib
.color_table_size
) count
= pdev
->dib
.color_table_size
- pos
;
477 memcpy( pdev
->dib
.color_table
+ pos
, colors
, count
* sizeof(RGBQUAD
) );
479 pdev
->bkgnd_color
= pdev
->dib
.funcs
->colorref_to_pixel( &pdev
->dib
, GetBkColor( dev
->hdc
) );
480 update_fg_colors( pdev
);
482 update_masks( pdev
, GetROP2( dev
->hdc
) );
484 return next
->funcs
->pSetDIBColorTable( next
, pos
, count
, colors
);
487 /***********************************************************************
490 static INT
dibdrv_SetROP2( PHYSDEV dev
, INT rop
)
492 PHYSDEV next
= GET_NEXT_PHYSDEV( dev
, pSetROP2
);
493 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
495 update_masks( pdev
, rop
);
497 return next
->funcs
->pSetROP2( next
, rop
);
500 const DC_FUNCTIONS dib_driver
=
502 NULL
, /* pAbortDoc */
503 NULL
, /* pAbortPath */
504 NULL
, /* pAlphaBlend */
505 NULL
, /* pAngleArc */
508 NULL
, /* pBeginPath */
509 NULL
, /* pBlendImage */
510 NULL
, /* pChoosePixelFormat */
512 NULL
, /* pCloseFigure */
513 NULL
, /* pCreateBitmap */
514 NULL
, /* pCreateCompatibleDC */
515 dibdrv_CreateDC
, /* pCreateDC */
516 NULL
, /* pCreateDIBSection */
517 NULL
, /* pDeleteBitmap */
518 dibdrv_DeleteDC
, /* pDeleteDC */
519 NULL
, /* pDeleteObject */
520 NULL
, /* pDescribePixelFormat */
521 NULL
, /* pDeviceCapabilities */
526 NULL
, /* pEnumDeviceFonts */
527 NULL
, /* pEnumICMProfiles */
528 NULL
, /* pExcludeClipRect */
529 NULL
, /* pExtDeviceMode */
530 NULL
, /* pExtEscape */
531 NULL
, /* pExtFloodFill */
532 NULL
, /* pExtSelectClipRgn */
533 NULL
, /* pExtTextOut */
534 NULL
, /* pFillPath */
536 NULL
, /* pFlattenPath */
537 NULL
, /* pFrameRgn */
538 NULL
, /* pGdiComment */
539 NULL
, /* pGetCharWidth */
540 NULL
, /* pGetDeviceCaps */
541 NULL
, /* pGetDeviceGammaRamp */
542 NULL
, /* pGetICMProfile */
543 dibdrv_GetImage
, /* pGetImage */
544 NULL
, /* pGetNearestColor */
545 NULL
, /* pGetPixel */
546 NULL
, /* pGetPixelFormat */
547 NULL
, /* pGetSystemPaletteEntries */
548 NULL
, /* pGetTextExtentExPoint */
549 NULL
, /* pGetTextMetrics */
550 NULL
, /* pIntersectClipRect */
551 NULL
, /* pInvertRgn */
552 dibdrv_LineTo
, /* pLineTo */
553 NULL
, /* pModifyWorldTransform */
555 NULL
, /* pOffsetClipRgn */
556 NULL
, /* pOffsetViewportOrg */
557 NULL
, /* pOffsetWindowOrg */
558 dibdrv_PaintRgn
, /* pPaintRgn */
559 dibdrv_PatBlt
, /* pPatBlt */
561 NULL
, /* pPolyBezier */
562 NULL
, /* pPolyBezierTo */
563 NULL
, /* pPolyDraw */
564 NULL
, /* pPolyPolygon */
565 dibdrv_PolyPolyline
, /* pPolyPolyline */
567 dibdrv_Polyline
, /* pPolyline */
568 NULL
, /* pPolylineTo */
569 dibdrv_PutImage
, /* pPutImage */
570 NULL
, /* pRealizeDefaultPalette */
571 NULL
, /* pRealizePalette */
572 dibdrv_Rectangle
, /* pRectangle */
574 NULL
, /* pRestoreDC */
575 NULL
, /* pRoundRect */
577 NULL
, /* pScaleViewportExt */
578 NULL
, /* pScaleWindowExt */
579 dibdrv_SelectBitmap
, /* pSelectBitmap */
580 dibdrv_SelectBrush
, /* pSelectBrush */
581 NULL
, /* pSelectClipPath */
582 NULL
, /* pSelectFont */
583 NULL
, /* pSelectPalette */
584 dibdrv_SelectPen
, /* pSelectPen */
585 NULL
, /* pSetArcDirection */
586 dibdrv_SetBkColor
, /* pSetBkColor */
587 dibdrv_SetBkMode
, /* pSetBkMode */
588 dibdrv_SetDCBrushColor
, /* pSetDCBrushColor */
589 dibdrv_SetDCPenColor
, /* pSetDCPenColor */
590 dibdrv_SetDIBColorTable
, /* pSetDIBColorTable */
591 NULL
, /* pSetDIBitsToDevice */
592 dibdrv_SetDeviceClipping
, /* pSetDeviceClipping */
593 NULL
, /* pSetDeviceGammaRamp */
594 NULL
, /* pSetLayout */
595 NULL
, /* pSetMapMode */
596 NULL
, /* pSetMapperFlags */
597 NULL
, /* pSetPixel */
598 NULL
, /* pSetPixelFormat */
599 NULL
, /* pSetPolyFillMode */
600 dibdrv_SetROP2
, /* pSetROP2 */
601 NULL
, /* pSetRelAbs */
602 NULL
, /* pSetStretchBltMode */
603 NULL
, /* pSetTextAlign */
604 NULL
, /* pSetTextCharacterExtra */
605 NULL
, /* pSetTextColor */
606 NULL
, /* pSetTextJustification */
607 NULL
, /* pSetViewportExt */
608 NULL
, /* pSetViewportOrg */
609 NULL
, /* pSetWindowExt */
610 NULL
, /* pSetWindowOrg */
611 NULL
, /* pSetWorldTransform */
612 NULL
, /* pStartDoc */
613 NULL
, /* pStartPage */
614 dibdrv_StretchBlt
, /* pStretchBlt */
615 NULL
, /* pStretchDIBits */
616 NULL
, /* pStrokeAndFillPath */
617 NULL
, /* pStrokePath */
618 NULL
, /* pSwapBuffers */
619 NULL
, /* pUnrealizePalette */
620 NULL
, /* pWidenPath */
621 NULL
, /* pwglCopyContext */
622 NULL
, /* pwglCreateContext */
623 NULL
, /* pwglCreateContextAttribsARB */
624 NULL
, /* pwglDeleteContext */
625 NULL
, /* pwglGetPbufferDCARB */
626 NULL
, /* pwglGetProcAddress */
627 NULL
, /* pwglMakeContextCurrentARB */
628 NULL
, /* pwglMakeCurrent */
629 NULL
, /* pwglSetPixelFormatWINE */
630 NULL
, /* pwglShareLists */
631 NULL
, /* pwglUseFontBitmapsA */
632 NULL
/* pwglUseFontBitmapsW */