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 static void init_dib_info(dib_info
*dib
, const BITMAPINFOHEADER
*bi
, const DWORD
*bit_fields
,
71 const RGBQUAD
*color_table
, void *bits
)
73 dib
->bit_count
= bi
->biBitCount
;
74 dib
->width
= bi
->biWidth
;
75 dib
->height
= bi
->biHeight
;
78 dib
->rect
.right
= bi
->biWidth
;
79 dib
->rect
.bottom
= abs( bi
->biHeight
);
80 dib
->compression
= bi
->biCompression
;
81 dib
->stride
= get_dib_stride( dib
->width
, dib
->bit_count
);
83 dib
->bits
.is_copy
= FALSE
;
84 dib
->bits
.free
= NULL
;
85 dib
->bits
.param
= NULL
;
87 if(dib
->height
< 0) /* top-down */
89 dib
->height
= -dib
->height
;
93 /* bits always points to the top-left corner and the stride is -ve */
94 dib
->bits
.ptr
= (BYTE
*)dib
->bits
.ptr
+ (dib
->height
- 1) * dib
->stride
;
95 dib
->stride
= -dib
->stride
;
98 dib
->funcs
= &funcs_null
;
100 switch(dib
->bit_count
)
103 if(bi
->biCompression
== BI_RGB
)
104 bit_fields
= bit_fields_888
;
106 init_bit_fields(dib
, bit_fields
);
108 if(dib
->red_mask
== 0xff0000 && dib
->green_mask
== 0x00ff00 && dib
->blue_mask
== 0x0000ff)
109 dib
->funcs
= &funcs_8888
;
111 dib
->funcs
= &funcs_32
;
115 dib
->funcs
= &funcs_24
;
119 if(bi
->biCompression
== BI_RGB
)
120 bit_fields
= bit_fields_555
;
122 init_bit_fields(dib
, bit_fields
);
124 if(dib
->red_mask
== 0x7c00 && dib
->green_mask
== 0x03e0 && dib
->blue_mask
== 0x001f)
125 dib
->funcs
= &funcs_555
;
127 dib
->funcs
= &funcs_16
;
131 dib
->funcs
= &funcs_8
;
135 dib
->funcs
= &funcs_4
;
139 dib
->funcs
= &funcs_1
;
143 if (color_table
&& bi
->biClrUsed
)
145 dib
->color_table
= color_table
;
146 dib
->color_table_size
= bi
->biClrUsed
;
150 dib
->color_table
= NULL
;
151 dib
->color_table_size
= 0;
155 void init_dib_info_from_bitmapinfo(dib_info
*dib
, const BITMAPINFO
*info
, void *bits
)
157 init_dib_info( dib
, &info
->bmiHeader
, (const DWORD
*)info
->bmiColors
, info
->bmiColors
, bits
);
160 BOOL
init_dib_info_from_bitmapobj(dib_info
*dib
, BITMAPOBJ
*bmp
)
162 if (!is_bitmapobj_dib( bmp
))
166 get_ddb_bitmapinfo( bmp
, &info
);
167 if (!bmp
->dib
.dsBm
.bmBits
)
169 int width_bytes
= get_dib_stride( bmp
->dib
.dsBm
.bmWidth
, bmp
->dib
.dsBm
.bmBitsPixel
);
170 bmp
->dib
.dsBm
.bmBits
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
171 bmp
->dib
.dsBm
.bmHeight
* width_bytes
);
172 if (!bmp
->dib
.dsBm
.bmBits
) return FALSE
;
174 init_dib_info_from_bitmapinfo( dib
, &info
, bmp
->dib
.dsBm
.bmBits
);
176 else init_dib_info( dib
, &bmp
->dib
.dsBmih
, bmp
->dib
.dsBitfields
,
177 bmp
->color_table
, bmp
->dib
.dsBm
.bmBits
);
181 static void clear_dib_info(dib_info
*dib
)
183 dib
->bits
.ptr
= NULL
;
184 dib
->bits
.free
= NULL
;
185 dib
->bits
.param
= NULL
;
188 /**********************************************************************
191 * Free the resources associated with a dib and optionally the bits
193 void free_dib_info(dib_info
*dib
)
195 if (dib
->bits
.free
) dib
->bits
.free( &dib
->bits
);
196 clear_dib_info( dib
);
199 void copy_dib_color_info(dib_info
*dst
, const dib_info
*src
)
201 dst
->bit_count
= src
->bit_count
;
202 dst
->red_mask
= src
->red_mask
;
203 dst
->green_mask
= src
->green_mask
;
204 dst
->blue_mask
= src
->blue_mask
;
205 dst
->red_len
= src
->red_len
;
206 dst
->green_len
= src
->green_len
;
207 dst
->blue_len
= src
->blue_len
;
208 dst
->red_shift
= src
->red_shift
;
209 dst
->green_shift
= src
->green_shift
;
210 dst
->blue_shift
= src
->blue_shift
;
211 dst
->funcs
= src
->funcs
;
212 dst
->color_table_size
= src
->color_table_size
;
213 dst
->color_table
= src
->color_table
;
216 DWORD
convert_bitmapinfo( const BITMAPINFO
*src_info
, void *src_bits
, struct bitblt_coords
*src
,
217 const BITMAPINFO
*dst_info
, void *dst_bits
, BOOL add_alpha
)
219 dib_info src_dib
, dst_dib
;
222 init_dib_info_from_bitmapinfo( &src_dib
, src_info
, src_bits
);
223 init_dib_info_from_bitmapinfo( &dst_dib
, dst_info
, dst_bits
);
227 dst_dib
.funcs
->convert_to( &dst_dib
, &src_dib
, &src
->visrect
, FALSE
);
232 WARN( "invalid bits pointer %p\n", src_bits
);
237 /* We shared the color tables, so there's no need to free the dib_infos here */
238 if(!ret
) return ERROR_BAD_FORMAT
;
240 /* update coordinates, the destination rectangle is always stored at 0,0 */
241 src
->x
-= src
->visrect
.left
;
242 src
->y
-= src
->visrect
.top
;
243 offset_rect( &src
->visrect
, -src
->visrect
.left
, -src
->visrect
.top
);
245 if (add_alpha
&& dst_dib
.funcs
== &funcs_8888
&& src_dib
.funcs
!= &funcs_8888
)
247 DWORD
*pixel
= dst_dib
.bits
.ptr
;
250 for (y
= src
->visrect
.top
; y
< src
->visrect
.bottom
; y
++, pixel
+= dst_dib
.stride
/ 4)
251 for (x
= src
->visrect
.left
; x
< src
->visrect
.right
; x
++)
252 pixel
[x
] |= 0xff000000;
255 return ERROR_SUCCESS
;
258 int get_clipped_rects( const dib_info
*dib
, const RECT
*rc
, HRGN clip
, struct clipped_rects
*clip_rects
)
260 const WINEREGION
*region
;
261 RECT rect
, *out
= clip_rects
->buffer
;
264 init_clipped_rects( clip_rects
);
266 rect
.left
= max( 0, -dib
->rect
.left
);
267 rect
.top
= max( 0, -dib
->rect
.top
);
268 rect
.right
= min( dib
->rect
.right
, dib
->width
) - dib
->rect
.left
;
269 rect
.bottom
= min( dib
->rect
.bottom
, dib
->height
) - dib
->rect
.top
;
270 if (is_rect_empty( &rect
)) return 0;
271 if (rc
&& !intersect_rect( &rect
, &rect
, rc
)) return 0;
276 clip_rects
->count
= 1;
280 if (!(region
= get_wine_region( clip
))) return 0;
282 for (i
= 0; i
< region
->numRects
; i
++)
284 if (region
->rects
[i
].top
>= rect
.bottom
) break;
285 if (!intersect_rect( out
, &rect
, ®ion
->rects
[i
] )) continue;
287 if (out
== &clip_rects
->buffer
[sizeof(clip_rects
->buffer
) / sizeof(RECT
)])
289 clip_rects
->rects
= HeapAlloc( GetProcessHeap(), 0, region
->numRects
* sizeof(RECT
) );
290 if (!clip_rects
->rects
) return 0;
291 memcpy( clip_rects
->rects
, clip_rects
->buffer
, (out
- clip_rects
->buffer
) * sizeof(RECT
) );
292 out
= clip_rects
->rects
+ (out
- clip_rects
->buffer
);
295 release_wine_region( clip
);
296 clip_rects
->count
= out
- clip_rects
->rects
;
297 return clip_rects
->count
;
300 void add_clipped_bounds( dibdrv_physdev
*dev
, const RECT
*rect
, HRGN clip
)
302 const WINEREGION
*region
;
305 if (!dev
->bounds
) return;
308 if (!(region
= get_wine_region( clip
))) return;
309 if (!rect
) rc
= region
->extents
;
310 else intersect_rect( &rc
, rect
, ®ion
->extents
);
311 release_wine_region( clip
);
315 if (is_rect_empty( &rc
)) return;
316 offset_rect( &rc
, dev
->dib
.rect
.left
, dev
->dib
.rect
.top
);
317 add_bounds_rect( dev
->bounds
, &rc
);
320 /**********************************************************************
323 static BOOL
dibdrv_CreateDC( PHYSDEV
*dev
, LPCWSTR driver
, LPCWSTR device
,
324 LPCWSTR output
, const DEVMODEW
*data
)
326 dibdrv_physdev
*pdev
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pdev
) );
328 if (!pdev
) return FALSE
;
329 clear_dib_info(&pdev
->dib
);
330 clear_dib_info(&pdev
->brush
.dib
);
331 clear_dib_info(&pdev
->pen_brush
.dib
);
332 push_dc_driver( dev
, &pdev
->dev
, &dib_driver
);
336 /***********************************************************************
339 static BOOL
dibdrv_DeleteDC( PHYSDEV dev
)
341 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
342 TRACE("(%p)\n", dev
);
343 free_pattern_brush( &pdev
->brush
);
344 free_pattern_brush( &pdev
->pen_brush
);
345 HeapFree( GetProcessHeap(), 0, pdev
);
349 /***********************************************************************
350 * dibdrv_SelectBitmap
352 static HBITMAP
dibdrv_SelectBitmap( PHYSDEV dev
, HBITMAP bitmap
)
354 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
355 BITMAPOBJ
*bmp
= GDI_GetObjPtr( bitmap
, OBJ_BITMAP
);
358 TRACE("(%p, %p)\n", dev
, bitmap
);
362 if (!init_dib_info_from_bitmapobj(&dib
, bmp
))
364 GDI_ReleaseObj( bitmap
);
368 GDI_ReleaseObj( bitmap
);
373 /***********************************************************************
374 * dibdrv_SetDeviceClipping
376 static void dibdrv_SetDeviceClipping( PHYSDEV dev
, HRGN rgn
)
378 dibdrv_physdev
*pdev
= get_dibdrv_pdev(dev
);
379 TRACE("(%p, %p)\n", dev
, rgn
);
384 /***********************************************************************
385 * dibdrv_SetBoundsRect
387 static UINT
dibdrv_SetBoundsRect( PHYSDEV dev
, RECT
*rect
, UINT flags
)
389 dibdrv_physdev
*pdev
= get_dibdrv_pdev( dev
);
391 if (flags
& DCB_DISABLE
) pdev
->bounds
= NULL
;
392 else if (flags
& DCB_ENABLE
) pdev
->bounds
= rect
;
393 return DCB_RESET
; /* we don't have device-specific bounds */
396 const struct gdi_dc_funcs dib_driver
=
398 NULL
, /* pAbortDoc */
399 NULL
, /* pAbortPath */
400 dibdrv_AlphaBlend
, /* pAlphaBlend */
401 NULL
, /* pAngleArc */
402 dibdrv_Arc
, /* pArc */
403 dibdrv_ArcTo
, /* pArcTo */
404 NULL
, /* pBeginPath */
405 dibdrv_BlendImage
, /* pBlendImage */
406 NULL
, /* pChoosePixelFormat */
407 dibdrv_Chord
, /* pChord */
408 NULL
, /* pCloseFigure */
409 NULL
, /* pCreateCompatibleDC */
410 dibdrv_CreateDC
, /* pCreateDC */
411 dibdrv_DeleteDC
, /* pDeleteDC */
412 NULL
, /* pDeleteObject */
413 NULL
, /* pDescribePixelFormat */
414 NULL
, /* pDeviceCapabilities */
415 dibdrv_Ellipse
, /* pEllipse */
419 NULL
, /* pEnumFonts */
420 NULL
, /* pEnumICMProfiles */
421 NULL
, /* pExcludeClipRect */
422 NULL
, /* pExtDeviceMode */
423 NULL
, /* pExtEscape */
424 dibdrv_ExtFloodFill
, /* pExtFloodFill */
425 NULL
, /* pExtSelectClipRgn */
426 dibdrv_ExtTextOut
, /* pExtTextOut */
427 NULL
, /* pFillPath */
429 NULL
, /* pFlattenPath */
430 NULL
, /* pFontIsLinked */
431 NULL
, /* pFrameRgn */
432 NULL
, /* pGdiComment */
433 NULL
, /* pGdiRealizationInfo */
434 NULL
, /* pGetBoundsRect */
435 NULL
, /* pGetCharABCWidths */
436 NULL
, /* pGetCharABCWidthsI */
437 NULL
, /* pGetCharWidth */
438 NULL
, /* pGetDeviceCaps */
439 NULL
, /* pGetDeviceGammaRamp */
440 NULL
, /* pGetFontData */
441 NULL
, /* pGetFontUnicodeRanges */
442 NULL
, /* pGetGlyphIndices */
443 NULL
, /* pGetGlyphOutline */
444 NULL
, /* pGetICMProfile */
445 dibdrv_GetImage
, /* pGetImage */
446 NULL
, /* pGetKerningPairs */
447 dibdrv_GetNearestColor
, /* pGetNearestColor */
448 NULL
, /* pGetOutlineTextMetrics */
449 dibdrv_GetPixel
, /* pGetPixel */
450 NULL
, /* pGetPixelFormat */
451 NULL
, /* pGetSystemPaletteEntries */
452 NULL
, /* pGetTextCharsetInfo */
453 NULL
, /* pGetTextExtentExPoint */
454 NULL
, /* pGetTextExtentExPointI */
455 NULL
, /* pGetTextFace */
456 NULL
, /* pGetTextMetrics */
457 dibdrv_GradientFill
, /* pGradientFill */
458 NULL
, /* pIntersectClipRect */
459 NULL
, /* pInvertRgn */
460 dibdrv_LineTo
, /* pLineTo */
461 NULL
, /* pModifyWorldTransform */
463 NULL
, /* pOffsetClipRgn */
464 NULL
, /* pOffsetViewportOrg */
465 NULL
, /* pOffsetWindowOrg */
466 dibdrv_PaintRgn
, /* pPaintRgn */
467 dibdrv_PatBlt
, /* pPatBlt */
468 dibdrv_Pie
, /* pPie */
469 NULL
, /* pPolyBezier */
470 NULL
, /* pPolyBezierTo */
471 NULL
, /* pPolyDraw */
472 dibdrv_PolyPolygon
, /* pPolyPolygon */
473 dibdrv_PolyPolyline
, /* pPolyPolyline */
474 dibdrv_Polygon
, /* pPolygon */
475 dibdrv_Polyline
, /* pPolyline */
476 NULL
, /* pPolylineTo */
477 dibdrv_PutImage
, /* pPutImage */
478 NULL
, /* pRealizeDefaultPalette */
479 NULL
, /* pRealizePalette */
480 dibdrv_Rectangle
, /* pRectangle */
482 NULL
, /* pRestoreDC */
483 dibdrv_RoundRect
, /* pRoundRect */
485 NULL
, /* pScaleViewportExt */
486 NULL
, /* pScaleWindowExt */
487 dibdrv_SelectBitmap
, /* pSelectBitmap */
488 dibdrv_SelectBrush
, /* pSelectBrush */
489 NULL
, /* pSelectClipPath */
490 NULL
, /* pSelectFont */
491 NULL
, /* pSelectPalette */
492 dibdrv_SelectPen
, /* pSelectPen */
493 NULL
, /* pSetArcDirection */
494 NULL
, /* pSetBkColor */
495 NULL
, /* pSetBkMode */
496 dibdrv_SetBoundsRect
, /* pSetBoundsRect */
497 dibdrv_SetDCBrushColor
, /* pSetDCBrushColor */
498 dibdrv_SetDCPenColor
, /* pSetDCPenColor */
499 NULL
, /* pSetDIBitsToDevice */
500 dibdrv_SetDeviceClipping
, /* pSetDeviceClipping */
501 NULL
, /* pSetDeviceGammaRamp */
502 NULL
, /* pSetLayout */
503 NULL
, /* pSetMapMode */
504 NULL
, /* pSetMapperFlags */
505 dibdrv_SetPixel
, /* pSetPixel */
506 NULL
, /* pSetPixelFormat */
507 NULL
, /* pSetPolyFillMode */
509 NULL
, /* pSetRelAbs */
510 NULL
, /* pSetStretchBltMode */
511 NULL
, /* pSetTextAlign */
512 NULL
, /* pSetTextCharacterExtra */
513 NULL
, /* pSetTextColor */
514 NULL
, /* pSetTextJustification */
515 NULL
, /* pSetViewportExt */
516 NULL
, /* pSetViewportOrg */
517 NULL
, /* pSetWindowExt */
518 NULL
, /* pSetWindowOrg */
519 NULL
, /* pSetWorldTransform */
520 NULL
, /* pStartDoc */
521 NULL
, /* pStartPage */
522 dibdrv_StretchBlt
, /* pStretchBlt */
523 NULL
, /* pStretchDIBits */
524 NULL
, /* pStrokeAndFillPath */
525 NULL
, /* pStrokePath */
526 NULL
, /* pSwapBuffers */
527 NULL
, /* pUnrealizePalette */
528 NULL
, /* pWidenPath */
529 NULL
, /* pwglCreateContext */
530 NULL
, /* pwglCreateContextAttribsARB */
531 NULL
, /* pwglGetProcAddress */
532 NULL
, /* wine_get_wgl_driver */
533 GDI_PRIORITY_DIB_DRV
/* priority */