gdi32: Get rid of the pen deferring support, all pen styles are implemented now.
[wine/multimedia.git] / dlls / gdi32 / dibdrv / graphics.c
blob1ba157b1e046d9b27876cfed8d9766983f73cfa6
1 /*
2 * DIB driver graphics operations.
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
21 #include <assert.h>
22 #include "gdi_private.h"
23 #include "dibdrv.h"
25 #include "wine/debug.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(dib);
29 static RECT get_device_rect( HDC hdc, int left, int top, int right, int bottom, BOOL rtl_correction )
31 RECT rect;
33 rect.left = left;
34 rect.top = top;
35 rect.right = right;
36 rect.bottom = bottom;
37 if (rtl_correction && GetLayout( hdc ) & LAYOUT_RTL)
39 /* shift the rectangle so that the right border is included after mirroring */
40 /* it would be more correct to do this after LPtoDP but that's not what Windows does */
41 rect.left--;
42 rect.right--;
44 LPtoDP( hdc, (POINT *)&rect, 2 );
45 if (rect.left > rect.right)
47 int tmp = rect.left;
48 rect.left = rect.right;
49 rect.right = tmp;
51 if (rect.top > rect.bottom)
53 int tmp = rect.top;
54 rect.top = rect.bottom;
55 rect.bottom = tmp;
57 return rect;
60 /* Intensities of the 17 glyph levels when drawn with text component of 0xff on a
61 black bkgnd. [A log-log plot of these data gives: y = 77.05 * x^0.4315]. */
62 static const BYTE ramp[17] =
64 0, 0x4d, 0x68, 0x7c,
65 0x8c, 0x9a, 0xa7, 0xb2,
66 0xbd, 0xc7, 0xd0, 0xd9,
67 0xe1, 0xe9, 0xf0, 0xf8,
68 0xff
71 /* For a give text-color component and a glyph level, calculate the
72 range of dst intensities, the min/max corresponding to 0/0xff bkgnd
73 components respectively.
75 The minimum is a linear interpolation between 0 and the value in
76 the ramp table.
78 The maximum is a linear interpolation between the value from the
79 ramp table read in reverse and 0xff.
81 To find the resulting pixel intensity, we note that if the text and
82 bkgnd intensities are the same then the result must be that
83 intensity. Otherwise we linearly interpolate between either the
84 min or the max value and this intermediate value depending on which
85 side of the inequality we lie.
88 static inline void get_range( BYTE aa, DWORD text_comp, BYTE *min_comp, BYTE *max_comp )
90 *min_comp = (ramp[aa] * text_comp) / 0xff;
91 *max_comp = ramp[16 - aa] + ((0xff - ramp[16 - aa]) * text_comp) / 0xff;
94 static inline void get_aa_ranges( COLORREF col, struct intensity_range intensities[17] )
96 int i;
98 for (i = 0; i < 17; i++)
100 get_range( i, GetRValue(col), &intensities[i].r_min, &intensities[i].r_max );
101 get_range( i, GetGValue(col), &intensities[i].g_min, &intensities[i].g_max );
102 get_range( i, GetBValue(col), &intensities[i].b_min, &intensities[i].b_max );
106 /**********************************************************************
107 * get_text_bkgnd_masks
109 * See the comment above get_pen_bkgnd_masks
111 static inline void get_text_bkgnd_masks( dibdrv_physdev *pdev, rop_mask *mask )
113 COLORREF bg = GetBkColor( pdev->dev.hdc );
115 mask->and = 0;
117 if (pdev->dib.bit_count != 1)
118 mask->xor = get_pixel_color( pdev, bg, FALSE );
119 else
121 COLORREF fg = GetTextColor( pdev->dev.hdc );
122 mask->xor = get_pixel_color( pdev, fg, TRUE );
123 if (fg != bg) mask->xor = ~mask->xor;
127 static void draw_glyph( dibdrv_physdev *pdev, const POINT *origin, const GLYPHMETRICS *metrics,
128 const struct gdi_image_bits *image, DWORD text_color,
129 const struct intensity_range *ranges, const struct clipped_rects *clipped_rects )
131 int i;
132 RECT rect, clipped_rect;
133 POINT src_origin;
134 dib_info glyph_dib;
136 glyph_dib.bit_count = 8;
137 glyph_dib.width = metrics->gmBlackBoxX;
138 glyph_dib.height = metrics->gmBlackBoxY;
139 glyph_dib.stride = get_dib_stride( metrics->gmBlackBoxX, 8 );
140 glyph_dib.bits = *image;
142 rect.left = origin->x + metrics->gmptGlyphOrigin.x;
143 rect.top = origin->y - metrics->gmptGlyphOrigin.y;
144 rect.right = rect.left + metrics->gmBlackBoxX;
145 rect.bottom = rect.top + metrics->gmBlackBoxY;
147 for (i = 0; i < clipped_rects->count; i++)
149 if (intersect_rect( &clipped_rect, &rect, clipped_rects->rects + i ))
151 src_origin.x = clipped_rect.left - rect.left;
152 src_origin.y = clipped_rect.top - rect.top;
154 pdev->dib.funcs->draw_glyph( &pdev->dib, &clipped_rect, &glyph_dib, &src_origin,
155 text_color, ranges );
160 static const BYTE masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
161 static const int padding[4] = {0, 3, 2, 1};
163 /***********************************************************************
164 * get_glyph_bitmap
166 * Retrieve a 17-level bitmap for the appropiate glyph.
168 * For non-antialiased bitmaps convert them to the 17-level format
169 * using only values 0 or 16.
171 static DWORD get_glyph_bitmap( HDC hdc, UINT index, UINT aa_flags, GLYPHMETRICS *metrics,
172 struct gdi_image_bits *image )
174 UINT ggo_flags = aa_flags | GGO_GLYPH_INDEX;
175 static const MAT2 identity = { {0,1}, {0,0}, {0,0}, {0,1} };
176 UINT indices[3] = {0, 0, 0x20};
177 int i, x, y;
178 DWORD ret, size;
179 BYTE *buf, *dst, *src;
180 int pad, stride;
182 image->ptr = NULL;
183 image->is_copy = FALSE;
184 image->free = free_heap_bits;
185 image->param = NULL;
187 indices[0] = index;
189 for (i = 0; i < sizeof(indices) / sizeof(indices[0]); i++)
191 index = indices[i];
192 ret = GetGlyphOutlineW( hdc, index, ggo_flags, metrics, 0, NULL, &identity );
193 if (ret != GDI_ERROR) break;
196 if (ret == GDI_ERROR) return ERROR_NOT_FOUND;
197 if (!ret) return ERROR_SUCCESS; /* empty glyph */
199 /* We'll convert non-antialiased 1-bpp bitmaps to 8-bpp, so these sizes relate to 8-bpp */
200 pad = padding[ metrics->gmBlackBoxX % 4 ];
201 stride = get_dib_stride( metrics->gmBlackBoxX, 8 );
202 size = metrics->gmBlackBoxY * stride;
204 buf = HeapAlloc( GetProcessHeap(), 0, size );
205 if (!buf) return ERROR_OUTOFMEMORY;
207 ret = GetGlyphOutlineW( hdc, index, ggo_flags, metrics, size, buf, &identity );
208 if (ret == GDI_ERROR)
210 HeapFree( GetProcessHeap(), 0, buf );
211 return ERROR_NOT_FOUND;
214 if (aa_flags == GGO_BITMAP)
216 for (y = metrics->gmBlackBoxY - 1; y >= 0; y--)
218 src = buf + y * get_dib_stride( metrics->gmBlackBoxX, 1 );
219 dst = buf + y * stride;
221 if (pad) memset( dst + metrics->gmBlackBoxX, 0, pad );
223 for (x = metrics->gmBlackBoxX - 1; x >= 0; x--)
224 dst[x] = (src[x / 8] & masks[x % 8]) ? 0x10 : 0;
227 else if (pad)
229 for (y = 0, dst = buf; y < metrics->gmBlackBoxY; y++, dst += stride)
230 memset( dst + metrics->gmBlackBoxX, 0, pad );
233 image->ptr = buf;
234 return ERROR_SUCCESS;
237 BOOL render_aa_text_bitmapinfo( HDC hdc, BITMAPINFO *info, struct gdi_image_bits *bits,
238 struct bitblt_coords *src, INT x, INT y, UINT flags,
239 UINT aa_flags, LPCWSTR str, UINT count, const INT *dx )
241 dib_info dib;
242 UINT i;
243 DWORD err;
244 BOOL got_pixel;
245 COLORREF fg, bg;
246 DWORD fg_pixel, bg_pixel;
247 struct intensity_range glyph_intensities[17];
249 assert( info->bmiHeader.biBitCount > 8 ); /* mono and indexed formats don't support anti-aliasing */
251 init_dib_info_from_bitmapinfo( &dib, info, bits->ptr, 0 );
253 fg = make_rgb_colorref( hdc, &dib, GetTextColor( hdc ), &got_pixel, &fg_pixel);
254 if (!got_pixel) fg_pixel = dib.funcs->colorref_to_pixel( &dib, fg );
256 get_aa_ranges( fg, glyph_intensities );
258 if (flags & ETO_OPAQUE)
260 rop_mask bkgnd_color;
262 bg = make_rgb_colorref( hdc, &dib, GetBkColor( hdc ), &got_pixel, &bg_pixel);
263 if (!got_pixel) bg_pixel = dib.funcs->colorref_to_pixel( &dib, bg );
265 bkgnd_color.and = 0;
266 bkgnd_color.xor = bg_pixel;
267 dib.funcs->solid_rects( &dib, 1, &src->visrect, bkgnd_color.and, bkgnd_color.xor );
270 for (i = 0; i < count; i++)
272 GLYPHMETRICS metrics;
273 struct gdi_image_bits image;
275 err = get_glyph_bitmap( hdc, (UINT)str[i], aa_flags, &metrics, &image );
276 if (err) continue;
278 if (image.ptr)
280 RECT rect, clipped_rect;
281 POINT src_origin;
282 dib_info glyph_dib;
284 glyph_dib.bit_count = 8;
285 glyph_dib.width = metrics.gmBlackBoxX;
286 glyph_dib.height = metrics.gmBlackBoxY;
287 glyph_dib.stride = get_dib_stride( metrics.gmBlackBoxX, 8 );
288 glyph_dib.bits = image;
290 rect.left = x + metrics.gmptGlyphOrigin.x;
291 rect.top = y - metrics.gmptGlyphOrigin.y;
292 rect.right = rect.left + metrics.gmBlackBoxX;
293 rect.bottom = rect.top + metrics.gmBlackBoxY;
295 if (intersect_rect( &clipped_rect, &rect, &src->visrect ))
297 src_origin.x = clipped_rect.left - rect.left;
298 src_origin.y = clipped_rect.top - rect.top;
300 dib.funcs->draw_glyph( &dib, &clipped_rect, &glyph_dib, &src_origin,
301 fg_pixel, glyph_intensities );
304 if (image.free) image.free( &image );
306 if (dx)
308 if (flags & ETO_PDY)
310 x += dx[ i * 2 ];
311 y += dx[ i * 2 + 1];
313 else
314 x += dx[ i ];
316 else
318 x += metrics.gmCellIncX;
319 y += metrics.gmCellIncY;
322 return TRUE;
325 /***********************************************************************
326 * dibdrv_ExtTextOut
328 BOOL dibdrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags,
329 const RECT *rect, LPCWSTR str, UINT count, const INT *dx )
331 dibdrv_physdev *pdev = get_dibdrv_pdev(dev);
332 struct clipped_rects clipped_rects;
333 UINT aa_flags, i;
334 POINT origin;
335 DWORD text_color, err;
336 struct intensity_range ranges[17];
338 init_clipped_rects( &clipped_rects );
340 if (flags & ETO_OPAQUE)
342 rop_mask bkgnd_color;
343 get_text_bkgnd_masks( pdev, &bkgnd_color );
344 get_clipped_rects( &pdev->dib, rect, pdev->clip, &clipped_rects );
345 pdev->dib.funcs->solid_rects( &pdev->dib, clipped_rects.count, clipped_rects.rects,
346 bkgnd_color.and, bkgnd_color.xor );
349 if (count == 0) goto done;
351 if (flags & ETO_CLIPPED)
353 if (!(flags & ETO_OPAQUE)) /* otherwise we have done it already */
354 get_clipped_rects( &pdev->dib, rect, pdev->clip, &clipped_rects );
356 else
358 free_clipped_rects( &clipped_rects );
359 get_clipped_rects( &pdev->dib, NULL, pdev->clip, &clipped_rects );
361 if (!clipped_rects.count) return TRUE;
363 text_color = get_pixel_color( pdev, GetTextColor( pdev->dev.hdc ), TRUE );
364 get_aa_ranges( pdev->dib.funcs->pixel_to_colorref( &pdev->dib, text_color ), ranges );
366 aa_flags = get_font_aa_flags( dev->hdc );
367 origin.x = x;
368 origin.y = y;
369 for (i = 0; i < count; i++)
371 GLYPHMETRICS metrics;
372 struct gdi_image_bits image;
374 err = get_glyph_bitmap( dev->hdc, (UINT)str[i], aa_flags, &metrics, &image );
375 if (err) continue;
377 if (image.ptr) draw_glyph( pdev, &origin, &metrics, &image, text_color, ranges, &clipped_rects );
378 if (image.free) image.free( &image );
380 if (dx)
382 if (flags & ETO_PDY)
384 origin.x += dx[ i * 2 ];
385 origin.y += dx[ i * 2 + 1];
387 else
388 origin.x += dx[ i ];
390 else
392 origin.x += metrics.gmCellIncX;
393 origin.y += metrics.gmCellIncY;
397 done:
398 free_clipped_rects( &clipped_rects );
399 return TRUE;
402 /***********************************************************************
403 * dibdrv_GetNearestColor
405 COLORREF dibdrv_GetNearestColor( PHYSDEV dev, COLORREF color )
407 dibdrv_physdev *pdev = get_dibdrv_pdev( dev );
408 DWORD pixel;
410 TRACE( "(%p, %08x)\n", dev, color );
412 pixel = get_pixel_color( pdev, color, FALSE );
413 return pdev->dib.funcs->pixel_to_colorref( &pdev->dib, pixel );
416 /***********************************************************************
417 * dibdrv_GetPixel
419 COLORREF dibdrv_GetPixel( PHYSDEV dev, INT x, INT y )
421 dibdrv_physdev *pdev = get_dibdrv_pdev( dev );
422 POINT pt;
423 DWORD pixel;
425 TRACE( "(%p, %d, %d)\n", dev, x, y );
427 pt.x = x;
428 pt.y = y;
429 LPtoDP( dev->hdc, &pt, 1 );
431 if (pt.x < 0 || pt.x >= pdev->dib.width ||
432 pt.y < 0 || pt.y >= pdev->dib.height)
433 return CLR_INVALID;
435 pixel = pdev->dib.funcs->get_pixel( &pdev->dib, &pt );
436 return pdev->dib.funcs->pixel_to_colorref( &pdev->dib, pixel );
439 /***********************************************************************
440 * dibdrv_LineTo
442 BOOL dibdrv_LineTo( PHYSDEV dev, INT x, INT y )
444 dibdrv_physdev *pdev = get_dibdrv_pdev(dev);
445 POINT pts[2];
446 HRGN region = 0;
447 BOOL ret;
449 GetCurrentPositionEx(dev->hdc, pts);
450 pts[1].x = x;
451 pts[1].y = y;
453 LPtoDP(dev->hdc, pts, 2);
455 if (pdev->pen_uses_region && !(region = CreateRectRgn( 0, 0, 0, 0 ))) return FALSE;
457 reset_dash_origin(pdev);
459 ret = pdev->pen_lines(pdev, 2, pts, FALSE, region);
461 if (region)
463 if (pdev->clip) CombineRgn( region, region, pdev->clip, RGN_AND );
464 ret = pen_region( pdev, region );
465 DeleteObject( region );
467 return ret;
470 /***********************************************************************
471 * get_rop2_from_rop
473 * Returns the binary rop that is equivalent to the provided ternary rop
474 * if the src bits are ignored.
476 static inline INT get_rop2_from_rop(INT rop)
478 return (((rop >> 18) & 0x0c) | ((rop >> 16) & 0x03)) + 1;
481 /***********************************************************************
482 * dibdrv_PatBlt
484 BOOL dibdrv_PatBlt( PHYSDEV dev, struct bitblt_coords *dst, DWORD rop )
486 dibdrv_physdev *pdev = get_dibdrv_pdev(dev);
488 TRACE("(%p, %d, %d, %d, %d, %06x)\n", dev, dst->x, dst->y, dst->width, dst->height, rop);
490 return brush_rect( pdev, &pdev->brush, &dst->visrect, pdev->clip, get_rop2_from_rop(rop) );
493 /***********************************************************************
494 * dibdrv_PaintRgn
496 BOOL dibdrv_PaintRgn( PHYSDEV dev, HRGN rgn )
498 dibdrv_physdev *pdev = get_dibdrv_pdev(dev);
499 const WINEREGION *region;
500 int i;
501 RECT rect;
503 TRACE("%p, %p\n", dev, rgn);
505 region = get_wine_region( rgn );
506 if(!region) return FALSE;
508 for(i = 0; i < region->numRects; i++)
510 rect = get_device_rect( dev->hdc, region->rects[i].left, region->rects[i].top,
511 region->rects[i].right, region->rects[i].bottom, FALSE );
512 brush_rect( pdev, &pdev->brush, &rect, pdev->clip, GetROP2( dev->hdc ) );
515 release_wine_region( rgn );
516 return TRUE;
519 /***********************************************************************
520 * dibdrv_PolyPolygon
522 BOOL dibdrv_PolyPolygon( PHYSDEV dev, const POINT *pt, const INT *counts, DWORD polygons )
524 dibdrv_physdev *pdev = get_dibdrv_pdev(dev);
525 DWORD total, i, pos;
526 BOOL ret = TRUE;
527 POINT *points;
528 HRGN outline = 0, interior = 0;
530 for (i = total = 0; i < polygons; i++)
532 if (counts[i] < 2) return FALSE;
533 total += counts[i];
536 points = HeapAlloc( GetProcessHeap(), 0, total * sizeof(*pt) );
537 if (!points) return FALSE;
538 memcpy( points, pt, total * sizeof(*pt) );
539 LPtoDP( dev->hdc, points, total );
541 if (pdev->brush.style != BS_NULL &&
542 !(interior = CreatePolyPolygonRgn( points, counts, polygons, GetPolyFillMode( dev->hdc ))))
544 HeapFree( GetProcessHeap(), 0, points );
545 return FALSE;
548 if (pdev->pen_uses_region) outline = CreateRectRgn( 0, 0, 0, 0 );
550 /* if not using a region, paint the interior first so the outline can overlap it */
551 if (interior && !outline)
553 ret = brush_region( pdev, interior );
554 DeleteObject( interior );
555 interior = 0;
558 for (i = pos = 0; i < polygons; i++)
560 reset_dash_origin( pdev );
561 pdev->pen_lines( pdev, counts[i], points + pos, TRUE, outline );
562 pos += counts[i];
565 if (interior)
567 CombineRgn( interior, interior, outline, RGN_DIFF );
568 ret = brush_region( pdev, interior );
569 DeleteObject( interior );
571 if (outline)
573 if (ret) ret = pen_region( pdev, outline );
574 DeleteObject( outline );
576 HeapFree( GetProcessHeap(), 0, points );
577 return ret;
580 /***********************************************************************
581 * dibdrv_PolyPolyline
583 BOOL dibdrv_PolyPolyline( PHYSDEV dev, const POINT* pt, const DWORD* counts, DWORD polylines )
585 dibdrv_physdev *pdev = get_dibdrv_pdev(dev);
586 DWORD max_points = 0, i;
587 POINT *points;
588 BOOL ret = TRUE;
589 HRGN outline = 0;
591 for (i = 0; i < polylines; i++)
593 if (counts[i] < 2) return FALSE;
594 max_points = max( counts[i], max_points );
597 points = HeapAlloc( GetProcessHeap(), 0, max_points * sizeof(*pt) );
598 if (!points) return FALSE;
600 if (pdev->pen_uses_region && !(outline = CreateRectRgn( 0, 0, 0, 0 )))
602 HeapFree( GetProcessHeap(), 0, points );
603 return FALSE;
606 for (i = 0; i < polylines; i++)
608 memcpy( points, pt, counts[i] * sizeof(*pt) );
609 pt += counts[i];
610 LPtoDP( dev->hdc, points, counts[i] );
612 reset_dash_origin( pdev );
613 pdev->pen_lines( pdev, counts[i], points, FALSE, outline );
616 if (outline)
618 if (pdev->clip) CombineRgn( outline, outline, pdev->clip, RGN_AND );
619 ret = pen_region( pdev, outline );
620 DeleteObject( outline );
623 HeapFree( GetProcessHeap(), 0, points );
624 return ret;
627 /***********************************************************************
628 * dibdrv_Polygon
630 BOOL dibdrv_Polygon( PHYSDEV dev, const POINT *pt, INT count )
632 INT counts[1] = { count };
634 return dibdrv_PolyPolygon( dev, pt, counts, 1 );
637 /***********************************************************************
638 * dibdrv_Polyline
640 BOOL dibdrv_Polyline( PHYSDEV dev, const POINT* pt, INT count )
642 DWORD counts[1] = { count };
644 if (count < 0) return FALSE;
645 return dibdrv_PolyPolyline( dev, pt, counts, 1 );
648 /***********************************************************************
649 * dibdrv_Rectangle
651 BOOL dibdrv_Rectangle( PHYSDEV dev, INT left, INT top, INT right, INT bottom )
653 dibdrv_physdev *pdev = get_dibdrv_pdev(dev);
654 RECT rect = get_device_rect( dev->hdc, left, top, right, bottom, TRUE );
655 POINT pts[4];
656 BOOL ret;
657 HRGN outline = 0;
659 TRACE("(%p, %d, %d, %d, %d)\n", dev, left, top, right, bottom);
661 if(rect.left == rect.right || rect.top == rect.bottom) return TRUE;
663 if (pdev->pen_style == PS_INSIDEFRAME)
665 rect.left += pdev->pen_width / 2;
666 rect.top += pdev->pen_width / 2;
667 rect.right -= (pdev->pen_width - 1) / 2;
668 rect.bottom -= (pdev->pen_width - 1) / 2;
671 if (pdev->pen_uses_region && !(outline = CreateRectRgn( 0, 0, 0, 0 ))) return FALSE;
673 rect.right--;
674 rect.bottom--;
675 reset_dash_origin(pdev);
677 /* 4 pts going anti-clockwise starting from top-right */
678 pts[0].x = pts[3].x = rect.right;
679 pts[0].y = pts[1].y = rect.top;
680 pts[1].x = pts[2].x = rect.left;
681 pts[2].y = pts[3].y = rect.bottom;
683 pdev->pen_lines(pdev, 4, pts, TRUE, outline);
685 if (outline)
687 if (pdev->brush.style != BS_NULL)
689 HRGN interior = CreateRectRgnIndirect( &rect );
691 CombineRgn( interior, interior, outline, RGN_DIFF );
692 brush_region( pdev, interior );
693 DeleteObject( interior );
695 ret = pen_region( pdev, outline );
696 DeleteObject( outline );
698 else
700 rect.left += (pdev->pen_width + 1) / 2;
701 rect.top += (pdev->pen_width + 1) / 2;
702 rect.right -= pdev->pen_width / 2;
703 rect.bottom -= pdev->pen_width / 2;
704 ret = brush_rect( pdev, &pdev->brush, &rect, pdev->clip, GetROP2(dev->hdc) );
706 return ret;
709 /***********************************************************************
710 * dibdrv_SetPixel
712 COLORREF dibdrv_SetPixel( PHYSDEV dev, INT x, INT y, COLORREF color )
714 dibdrv_physdev *pdev = get_dibdrv_pdev( dev );
715 struct clipped_rects clipped_rects;
716 RECT rect;
717 POINT pt;
718 DWORD pixel;
720 TRACE( "(%p, %d, %d, %08x)\n", dev, x, y, color );
722 pt.x = x;
723 pt.y = y;
724 LPtoDP( dev->hdc, &pt, 1 );
725 rect.left = pt.x;
726 rect.top = pt.y;
727 rect.right = rect.left + 1;
728 rect.bottom = rect.top + 1;
730 /* SetPixel doesn't do the 1bpp massaging like other fg colors */
731 pixel = get_pixel_color( pdev, color, FALSE );
732 color = pdev->dib.funcs->pixel_to_colorref( &pdev->dib, pixel );
734 if (!get_clipped_rects( &pdev->dib, &rect, pdev->clip, &clipped_rects )) return color;
735 pdev->dib.funcs->solid_rects( &pdev->dib, clipped_rects.count, clipped_rects.rects, 0, pixel );
736 free_clipped_rects( &clipped_rects );
737 return color;