2 * DIBDRV depth specific DIB rendering functions
4 * Copyright 2007 Jesse Allen
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
26 #include "wine/debug.h"
28 #include "dib_render.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(dibdrv
);
32 /* DIB_GetColorTableEntry: Return color components of the requested color table entry. */
33 void DIB_GetColorTableEntry( DIBDRVBITMAP
*bmp
, BYTE i
, BYTE
*r
, BYTE
*g
, BYTE
*b
)
35 *r
= bmp
->color_table
[i
].rgbRed
;
36 *g
= bmp
->color_table
[i
].rgbGreen
;
37 *b
= bmp
->color_table
[i
].rgbBlue
;
40 /* DIB_GetNearestIndex: Return closest matching color table entry. */
41 INT
DIB_GetNearestIndex( DIBDRVBITMAP
*bmp
, BYTE r
, BYTE g
, BYTE b
)
43 INT i
, diff
, bestdiff
= -1, ret
= 0;
44 for (i
= 0; i
< bmp
->nb_colors
; i
++)
46 diff
= (bmp
->color_table
[i
].rgbBlue
- b
)*(bmp
->color_table
[i
].rgbBlue
- b
) +
47 (bmp
->color_table
[i
].rgbGreen
- g
)*(bmp
->color_table
[i
].rgbGreen
- g
) +
48 (bmp
->color_table
[i
].rgbRed
- r
)*(bmp
->color_table
[i
].rgbRed
- r
);
51 if (bestdiff
== -1 || diff
< bestdiff
)
60 /* DIB16_EncodeColor: helper to encode a pixel for a 16 bpp DIB. */
61 WORD
DIB16_EncodeColor( DIBDRVBITMAP
*bmp
, BYTE r
, BYTE g
, BYTE b
)
63 return (r
>> bmp
->bf_shift
[0]) << bmp
->bf_pos
[0] |
64 (g
>> bmp
->bf_shift
[1]) << bmp
->bf_pos
[1] |
65 (b
>> bmp
->bf_shift
[2]) << bmp
->bf_pos
[2];
68 /* DIB32_EncodeColor: helper to encode a pixel for a 32 bpp DIB. */
69 DWORD
DIB32_EncodeColor( DIBDRVBITMAP
*bmp
, BYTE r
, BYTE g
, BYTE b
)
71 return ((r
>> bmp
->bf_shift
[0]) << bmp
->bf_pos
[0]) |
72 ((g
>> bmp
->bf_shift
[1]) << bmp
->bf_pos
[1]) |
73 ((b
>> bmp
->bf_shift
[2]) << bmp
->bf_pos
[2]);
78 * AdvancePosition(): Move drawing location relative to current position by the requested number
79 * of pixels. It is the caller's responsibility to traverse scan lines correctly, as this does
82 * Copy(): Copy the requested number of pixels from source DIB to destination DIB performing format
83 * conversions as necessary. Since this requires two images, call the Copy() member of the
84 * destination image, pass the source conversion function table, and copy translates the call into
85 * the appropriate conversion routine. The caller is responsible to traverse scan lines
88 * MoveXY(): Move drawing location using X,Y coordinates. Stores address with whatever shifting
89 * required to correct value. Returns a BOOL where FALSE means an attempt to move out of range.
91 * ReadColor(): Read pixel and translate into color components.
93 * SelectColor(): Store a color encoded for the DIB.
95 * SetPixel(): Optimized SetPixel for GDI by writing a COLORREF directly.
97 * WriteColor(): Write a number of pixels with stored color.
100 void DIB1_AdvancePosition( DIBDRVBITMAP
*bmp
, int n
)
103 while (bmp
->shift
< 0)
105 bmp
->addr
= (BYTE
*)bmp
->addr
+ 1;
110 void DIB1_Copy( DIBDRVBITMAP
*dst
, DIBDRVBITMAP
*src
, int num_pixels
, const DIBCONVERT
*convs
)
112 convs
->ConvertToDIB1( dst
, src
, num_pixels
);
115 void DIB1_MoveXY( DIBDRVBITMAP
*bmp
, INT x
, INT y
)
117 unsigned int r
= (unsigned int)bmp
->bits
+ y
*bmp
->widthbytes
+ x
/8; /* 1 byte per 8 pixels */
118 bmp
->shift
= 7 - x
% 8; /* maximum shift within unsigned char: 7 */
119 bmp
->addr
= (void *)r
;
122 void DIB1_ReadColor( DIBDRVBITMAP
*bmp
, BYTE
*r
, BYTE
*g
, BYTE
*b
)
124 DIB_GetColorTableEntry( bmp
, (*(BYTE
*)bmp
->addr
>> bmp
->shift
) & 1, r
, g
, b
);
127 /* DIB1_SelectColor ----> DIB8_SelectColor */
129 void DIB1_SetPixel( DIBDRVBITMAP
*bmp
, COLORREF c
)
132 *p
= DIB_GetNearestIndex( bmp
, GetRValue( c
), GetGValue( c
), GetBValue( c
) ) ?
133 *p
| 1 << bmp
->shift
: *p
& ~(1 << bmp
->shift
);
136 void DIB1_WriteColor( DIBDRVBITMAP
*bmp
, int num_pixels
)
139 for (i
= 0; i
< num_pixels
; i
++)
142 *p
= bmp
->color8
? *p
| 1 << bmp
->shift
: *p
& ~(1 << bmp
->shift
);
143 DIB1_AdvancePosition( bmp
, 1 );
147 void DIB4_AdvancePosition( DIBDRVBITMAP
*bmp
, int n
)
150 while (bmp
->shift
< 0)
152 bmp
->addr
= (BYTE
*)bmp
->addr
+ 1;
157 void DIB4_Copy( DIBDRVBITMAP
*dst
, DIBDRVBITMAP
*src
, int num_pixels
, const DIBCONVERT
*convs
)
159 convs
->ConvertToDIB4( dst
, src
, num_pixels
);
162 void DIB4_MoveXY( DIBDRVBITMAP
*bmp
, INT x
, INT y
)
164 unsigned int r
= (unsigned int)bmp
->bits
+ y
*bmp
->widthbytes
+ x
/2; /* 1 byte per 2 pixels */
165 bmp
->shift
= x
% 2; /* If true, we need the first 4 bits */
166 bmp
->addr
= (void *)r
;
169 void DIB4_ReadColor( DIBDRVBITMAP
*bmp
, BYTE
*r
, BYTE
*g
, BYTE
*b
)
171 DIB_GetColorTableEntry( bmp
,
172 bmp
->shift
? *(BYTE
*)bmp
->addr
& 0xf : *(BYTE
*)bmp
->addr
>> 4,
176 /* DIB4_SelectColor ----> DIB8_SelectColor */
178 void DIB4_SetPixel( DIBDRVBITMAP
*bmp
, COLORREF c
)
183 DIB_GetNearestIndex( bmp
, GetRValue( c
), GetGValue( c
), GetBValue( c
) ) :
185 (DIB_GetNearestIndex( bmp
, GetRValue( c
), GetGValue( c
), GetBValue( c
) ) << 4);
188 void DIB4_WriteColor( DIBDRVBITMAP
*bmp
, int num_pixels
)
191 for (i
= 0; i
< num_pixels
; i
++)
194 *p
= bmp
->shift
? (*p
& 0xf0)|bmp
->color8
: (*p
& 0xf)|(bmp
->color8
<< 4);
195 DIB4_AdvancePosition( bmp
, 1 );
199 void DIB8_AdvancePosition( DIBDRVBITMAP
*bmp
, int n
)
201 bmp
->addr
= (BYTE
*)bmp
->addr
+ n
;
204 void DIB8_Copy( DIBDRVBITMAP
*dst
, DIBDRVBITMAP
*src
, int num_pixels
, const DIBCONVERT
*convs
)
206 convs
->ConvertToDIB8( dst
, src
, num_pixels
);
209 void DIB8_MoveXY( DIBDRVBITMAP
*bmp
, INT x
, INT y
)
211 unsigned int r
= (unsigned int)bmp
->bits
+ y
*bmp
->widthbytes
+ x
; /* 1 byte per 1 pixel */
212 bmp
->addr
= (void *)r
;
215 void DIB8_ReadColor( DIBDRVBITMAP
*bmp
, BYTE
*r
, BYTE
*g
, BYTE
*b
)
217 DIB_GetColorTableEntry( bmp
, *(BYTE
*)bmp
->addr
, r
, g
, b
);
220 void DIB8_SelectColor( DIBDRVBITMAP
*bmp
, COLORREF c
)
222 bmp
->color8
= DIB_GetNearestIndex( bmp
, GetRValue( c
), GetGValue( c
), GetBValue( c
) );
225 void DIB8_SetPixel( DIBDRVBITMAP
*bmp
, COLORREF c
)
227 *(BYTE
*)bmp
->addr
= DIB_GetNearestIndex( bmp
,
228 GetRValue( c
), GetGValue( c
), GetBValue( c
) );
231 void DIB8_WriteColor( DIBDRVBITMAP
*bmp
, int num_pixels
)
234 for (i
= 0; i
< num_pixels
; i
++)
236 *(BYTE
*)bmp
->addr
= bmp
->color8
;
237 DIB8_AdvancePosition( bmp
, 1 );
241 void DIB16_AdvancePosition( DIBDRVBITMAP
*bmp
, int n
)
243 bmp
->addr
= (WORD
*)bmp
->addr
+ n
;
246 void DIB16_Copy( DIBDRVBITMAP
*dst
, DIBDRVBITMAP
*src
, int num_pixels
, const DIBCONVERT
*convs
)
248 convs
->ConvertToDIB16( dst
, src
, num_pixels
);
251 void DIB16_MoveXY( DIBDRVBITMAP
*bmp
, INT x
, INT y
)
253 unsigned int addr
= (unsigned int)bmp
->bits
+ y
*bmp
->widthbytes
+ x
*2; /* 2 bytes per pixel */
254 bmp
->addr
= (void *)addr
;
257 void DIB16_ReadColor( DIBDRVBITMAP
*bmp
, BYTE
*r
, BYTE
*g
, BYTE
*b
)
260 *r
= (*p
& bmp
->bitfields
[0]) >> bmp
->bf_pos
[0] << bmp
->bf_shift
[0];
261 *g
= (*p
& bmp
->bitfields
[1]) >> bmp
->bf_pos
[1] << bmp
->bf_shift
[1];
262 *b
= (*p
& bmp
->bitfields
[2]) >> bmp
->bf_pos
[2] << bmp
->bf_shift
[2];
263 if (bmp
->bf_size
[0] < 8) *r
|= *r
>> bmp
->bf_size
[0];
264 if (bmp
->bf_size
[1] < 8) *g
|= *g
>> bmp
->bf_size
[1];
265 if (bmp
->bf_size
[2] < 8) *b
|= *b
>> bmp
->bf_size
[2];
268 void DIB16_SelectColor( DIBDRVBITMAP
*bmp
, COLORREF c
)
270 bmp
->color16
= DIB16_EncodeColor( bmp
, GetRValue( c
), GetGValue( c
), GetBValue( c
) );
273 void DIB16_SetPixel( DIBDRVBITMAP
*bmp
, COLORREF c
)
275 *(WORD
*)bmp
->addr
= DIB16_EncodeColor( bmp
, GetRValue( c
), GetGValue( c
), GetBValue( c
) );
278 void DIB16_WriteColor( DIBDRVBITMAP
*bmp
, int num_pixels
)
281 for (i
= 0; i
< num_pixels
; i
++)
283 *(WORD
*)bmp
->addr
= bmp
->color16
;
284 DIB16_AdvancePosition( bmp
, 1 );
288 void DIB24_AdvancePosition( DIBDRVBITMAP
*bmp
, int n
)
290 bmp
->addr
= (RGBTRIPLE
*)bmp
->addr
+ n
;
293 void DIB24_Copy( DIBDRVBITMAP
*dst
, DIBDRVBITMAP
*src
, int num_pixels
, const DIBCONVERT
*convs
)
295 convs
->ConvertToDIB24( dst
, src
, num_pixels
);
298 void DIB24_MoveXY( DIBDRVBITMAP
*bmp
, INT x
, INT y
)
300 unsigned int addr
= (unsigned int)bmp
->bits
+ y
*bmp
->widthbytes
+ x
*3; /* 3 bytes per pixel */
301 bmp
->addr
= (void *)addr
;
304 void DIB24_ReadColor( DIBDRVBITMAP
*bmp
, BYTE
*r
, BYTE
*g
, BYTE
*b
)
306 RGBTRIPLE
*p
= bmp
->addr
;
312 void DIB24_SelectColor( DIBDRVBITMAP
*bmp
, COLORREF c
)
314 bmp
->color24
.rgbtRed
= GetRValue( c
);
315 bmp
->color24
.rgbtGreen
= GetGValue( c
);
316 bmp
->color24
.rgbtBlue
= GetBValue( c
);
319 void DIB24_SetPixel( DIBDRVBITMAP
*bmp
, COLORREF c
)
321 RGBTRIPLE
*p
= bmp
->addr
;
322 p
->rgbtRed
= GetRValue( c
);
323 p
->rgbtGreen
= GetGValue( c
);
324 p
->rgbtBlue
= GetBValue( c
);
327 void DIB24_WriteColor( DIBDRVBITMAP
*bmp
, int num_pixels
)
330 for (i
= 0; i
< num_pixels
; i
++)
332 RGBTRIPLE
*p
= bmp
->addr
;
333 p
->rgbtRed
= bmp
->color24
.rgbtRed
;
334 p
->rgbtGreen
= bmp
->color24
.rgbtGreen
;
335 p
->rgbtBlue
= bmp
->color24
.rgbtBlue
;
336 DIB24_AdvancePosition( bmp
, 1 );
340 void DIB32_AdvancePosition( DIBDRVBITMAP
*bmp
, int n
)
342 bmp
->addr
= (DWORD
*)bmp
->addr
+ n
;
345 void DIB32_Copy( DIBDRVBITMAP
*dst
, DIBDRVBITMAP
*src
, int num_pixels
, const DIBCONVERT
*convs
)
347 convs
->ConvertToDIB32( dst
, src
, num_pixels
);
350 void DIB32_MoveXY( DIBDRVBITMAP
*bmp
, INT x
, INT y
)
352 unsigned int addr
= (unsigned int)bmp
->bits
+ y
*bmp
->widthbytes
+ x
*4; /* 4 bytes per pixel */
353 bmp
->addr
= (void *)addr
;
356 void DIB32_ReadColor( DIBDRVBITMAP
*bmp
, BYTE
*r
, BYTE
*g
, BYTE
*b
)
358 DWORD
*p
= bmp
->addr
;
359 *r
= (*p
& bmp
->bitfields
[0]) >> bmp
->bf_pos
[0] << bmp
->bf_shift
[0];
360 *g
= (*p
& bmp
->bitfields
[1]) >> bmp
->bf_pos
[1] << bmp
->bf_shift
[1];
361 *b
= (*p
& bmp
->bitfields
[2]) >> bmp
->bf_pos
[2] << bmp
->bf_shift
[2];
362 if (bmp
->bf_size
[0] < 8) *r
|= *r
>> bmp
->bf_size
[0];
363 if (bmp
->bf_size
[1] < 8) *g
|= *g
>> bmp
->bf_size
[1];
364 if (bmp
->bf_size
[2] < 8) *b
|= *b
>> bmp
->bf_size
[2];
367 void DIB32_SelectColor( DIBDRVBITMAP
*bmp
, COLORREF c
)
369 bmp
->color32
= DIB32_EncodeColor( bmp
, GetRValue( c
), GetGValue( c
), GetBValue( c
) );
372 void DIB32_SetPixel( DIBDRVBITMAP
*bmp
, COLORREF c
)
374 *(DWORD
*)bmp
->addr
= DIB32_EncodeColor( bmp
, GetRValue( c
), GetGValue( c
), GetBValue( c
) );
377 void DIB32_WriteColor( DIBDRVBITMAP
*bmp
, int num_pixels
)
380 for (i
= 0; i
< num_pixels
; i
++)
382 *(DWORD
*)bmp
->addr
= bmp
->color32
;
383 DIB32_AdvancePosition( bmp
, 1 );
387 const DIBFUNCS DIB1_funcs
=
389 &DIB1_AdvancePosition
,
398 const DIBFUNCS DIB4_funcs
=
400 &DIB4_AdvancePosition
,
409 const DIBFUNCS DIB8_funcs
=
411 &DIB8_AdvancePosition
,
420 const DIBFUNCS DIB16_funcs
=
422 &DIB16_AdvancePosition
,
431 const DIBFUNCS DIB24_funcs
=
433 &DIB24_AdvancePosition
,
442 const DIBFUNCS DIB32_funcs
=
444 &DIB32_AdvancePosition
,