gdi32: Implement brushed pens.
This commit is contained in:
parent
4e03247427
commit
488bf107a9
|
@ -309,6 +309,7 @@ static BOOL dibdrv_CreateDC( PHYSDEV *dev, LPCWSTR driver, LPCWSTR device,
|
|||
if (!pdev) return FALSE;
|
||||
clear_dib_info(&pdev->dib);
|
||||
clear_dib_info(&pdev->brush.dib);
|
||||
clear_dib_info(&pdev->pen_brush.dib);
|
||||
push_dc_driver( dev, &pdev->dev, &dib_driver );
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -321,6 +322,7 @@ static BOOL dibdrv_DeleteDC( PHYSDEV dev )
|
|||
dibdrv_physdev *pdev = get_dibdrv_pdev(dev);
|
||||
TRACE("(%p)\n", dev);
|
||||
free_pattern_brush( &pdev->brush );
|
||||
free_pattern_brush( &pdev->pen_brush );
|
||||
HeapFree( GetProcessHeap(), 0, pdev );
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -389,7 +391,11 @@ static UINT dibdrv_SetDIBColorTable( PHYSDEV dev, UINT pos, UINT count, const RG
|
|||
dibdrv_physdev *pdev = get_dibdrv_pdev(dev);
|
||||
TRACE("(%p, %d, %d, %p)\n", dev, pos, count, colors);
|
||||
|
||||
if (pdev->dib.color_table) pdev->brush.rop = -1; /* force re-creating the brush bits */
|
||||
if (pdev->dib.color_table) /* force re-creating the brush bits */
|
||||
{
|
||||
pdev->brush.rop = -1;
|
||||
pdev->pen_brush.rop = -1;
|
||||
}
|
||||
|
||||
return next->funcs->pSetDIBColorTable( next, pos, count, colors );
|
||||
}
|
||||
|
|
|
@ -99,10 +99,10 @@ typedef struct dibdrv_physdev
|
|||
DWORD defer;
|
||||
|
||||
/* pen */
|
||||
COLORREF pen_colorref;
|
||||
DWORD pen_style, pen_endcap, pen_join;
|
||||
BOOL pen_uses_region, pen_is_ext;
|
||||
int pen_width;
|
||||
dib_brush pen_brush;
|
||||
dash_pattern pen_pattern;
|
||||
dash_pos dash_pos;
|
||||
rop_mask dash_masks[2];
|
||||
|
|
|
@ -758,7 +758,7 @@ static BOOL solid_pen_lines(dibdrv_physdev *pdev, int num, POINT *pts, BOOL clos
|
|||
{
|
||||
DWORD color, and, xor;
|
||||
|
||||
color = get_pixel_color( pdev, pdev->pen_colorref, TRUE );
|
||||
color = get_pixel_color( pdev, pdev->pen_brush.colorref, TRUE );
|
||||
calc_and_xor_masks( GetROP2(pdev->dev.hdc), color, &and, &xor );
|
||||
|
||||
for (i = 0; i < num - 1; i++)
|
||||
|
@ -1190,7 +1190,7 @@ static BOOL dashed_pen_lines(dibdrv_physdev *pdev, int num, POINT *pts, BOOL clo
|
|||
}
|
||||
else
|
||||
{
|
||||
get_color_masks( pdev, GetROP2(pdev->dev.hdc), pdev->pen_colorref,
|
||||
get_color_masks( pdev, GetROP2(pdev->dev.hdc), pdev->pen_brush.colorref,
|
||||
pdev->pen_is_ext ? TRANSPARENT : GetBkMode(pdev->dev.hdc),
|
||||
&pdev->dash_masks[1], &pdev->dash_masks[0] );
|
||||
|
||||
|
@ -1528,112 +1528,6 @@ static inline int get_pen_device_width( dibdrv_physdev *pdev, int width )
|
|||
return max( width, 1 );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* dibdrv_SelectPen
|
||||
*/
|
||||
HPEN dibdrv_SelectPen( PHYSDEV dev, HPEN hpen, const struct brush_pattern *pattern )
|
||||
{
|
||||
PHYSDEV next = GET_NEXT_PHYSDEV( dev, pSelectPen );
|
||||
dibdrv_physdev *pdev = get_dibdrv_pdev(dev);
|
||||
LOGPEN logpen;
|
||||
EXTLOGPEN *elp = NULL;
|
||||
|
||||
TRACE("(%p, %p)\n", dev, hpen);
|
||||
|
||||
if (!GetObjectW( hpen, sizeof(logpen), &logpen ))
|
||||
{
|
||||
/* must be an extended pen */
|
||||
INT size = GetObjectW( hpen, 0, NULL );
|
||||
|
||||
if (!size) return 0;
|
||||
|
||||
elp = HeapAlloc( GetProcessHeap(), 0, size );
|
||||
|
||||
GetObjectW( hpen, size, elp );
|
||||
/* FIXME: add support for user style pens */
|
||||
logpen.lopnStyle = elp->elpPenStyle;
|
||||
logpen.lopnWidth.x = elp->elpWidth;
|
||||
logpen.lopnColor = elp->elpColor;
|
||||
/* cosmetic ext pens are always 1-pixel wide */
|
||||
if (!(logpen.lopnStyle & PS_GEOMETRIC)) logpen.lopnWidth.x = 0;
|
||||
}
|
||||
|
||||
pdev->pen_join = logpen.lopnStyle & PS_JOIN_MASK;
|
||||
pdev->pen_endcap = logpen.lopnStyle & PS_ENDCAP_MASK;
|
||||
pdev->pen_width = get_pen_device_width( pdev, logpen.lopnWidth.x );
|
||||
|
||||
if (hpen == GetStockObject( DC_PEN ))
|
||||
logpen.lopnColor = GetDCPenColor( dev->hdc );
|
||||
|
||||
pdev->pen_colorref = logpen.lopnColor;
|
||||
set_dash_pattern( &pdev->pen_pattern, 0, NULL );
|
||||
|
||||
pdev->defer |= DEFER_PEN;
|
||||
|
||||
pdev->pen_style = logpen.lopnStyle & PS_STYLE_MASK;
|
||||
|
||||
switch (pdev->pen_style)
|
||||
{
|
||||
case PS_DASH:
|
||||
case PS_DOT:
|
||||
case PS_DASHDOT:
|
||||
case PS_DASHDOTDOT:
|
||||
if (logpen.lopnStyle & PS_GEOMETRIC)
|
||||
{
|
||||
if (pdev->pen_width > 1) break; /* not supported yet */
|
||||
pdev->pen_lines = dashed_pen_lines;
|
||||
pdev->pen_pattern = dash_patterns_geometric[pdev->pen_style - 1];
|
||||
pdev->defer &= ~DEFER_PEN;
|
||||
break;
|
||||
}
|
||||
if (pdev->pen_width == 1) /* wide cosmetic pens are not dashed */
|
||||
{
|
||||
pdev->pen_lines = dashed_pen_lines;
|
||||
pdev->pen_pattern = dash_patterns_cosmetic[pdev->pen_style - 1];
|
||||
pdev->defer &= ~DEFER_PEN;
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
case PS_SOLID:
|
||||
case PS_INSIDEFRAME:
|
||||
if(pdev->pen_width == 1)
|
||||
pdev->pen_lines = solid_pen_lines;
|
||||
else
|
||||
pdev->pen_lines = wide_pen_lines;
|
||||
pdev->defer &= ~DEFER_PEN;
|
||||
break;
|
||||
|
||||
case PS_NULL:
|
||||
pdev->pen_width = 0;
|
||||
pdev->pen_lines = null_pen_lines;
|
||||
pdev->defer &= ~DEFER_PEN;
|
||||
break;
|
||||
|
||||
case PS_ALTERNATE:
|
||||
pdev->pen_lines = dashed_pen_lines;
|
||||
pdev->pen_pattern = dash_patterns_geometric[PS_DOT - 1];
|
||||
pdev->defer &= ~DEFER_PEN;
|
||||
break;
|
||||
|
||||
case PS_USERSTYLE:
|
||||
if (pdev->pen_width > 1) break; /* not supported yet */
|
||||
pdev->pen_lines = dashed_pen_lines;
|
||||
set_dash_pattern( &pdev->pen_pattern, elp->elpNumEntries, elp->elpStyleEntry );
|
||||
if (!(logpen.lopnStyle & PS_GEOMETRIC)) scale_dash_pattern( &pdev->pen_pattern, 3 );
|
||||
pdev->defer &= ~DEFER_PEN;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
pdev->pen_uses_region = (logpen.lopnStyle & PS_GEOMETRIC || pdev->pen_width > 1);
|
||||
pdev->pen_is_ext = (elp != NULL);
|
||||
HeapFree( GetProcessHeap(), 0, elp );
|
||||
|
||||
return next->funcs->pSelectPen( next, hpen, pattern );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* dibdrv_SetDCPenColor
|
||||
*/
|
||||
|
@ -1643,7 +1537,7 @@ COLORREF dibdrv_SetDCPenColor( PHYSDEV dev, COLORREF color )
|
|||
dibdrv_physdev *pdev = get_dibdrv_pdev(dev);
|
||||
|
||||
if (GetCurrentObject(dev->hdc, OBJ_PEN) == GetStockObject( DC_PEN ))
|
||||
pdev->pen_colorref = color;
|
||||
pdev->pen_brush.colorref = color;
|
||||
|
||||
return next->funcs->pSetDCPenColor( next, color );
|
||||
}
|
||||
|
@ -1929,6 +1823,31 @@ static BOOL null_brush(dibdrv_physdev *pdev, dib_brush *brush, dib_info *dib,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void select_brush( dib_brush *brush, const LOGBRUSH *logbrush, const struct brush_pattern *pattern )
|
||||
{
|
||||
free_pattern_brush( brush );
|
||||
|
||||
if (pattern)
|
||||
{
|
||||
brush->style = BS_DIBPATTERN;
|
||||
brush->pattern = *pattern; /* brush is actually selected only when it's used */
|
||||
brush->rects = pattern_brush;
|
||||
}
|
||||
else
|
||||
{
|
||||
brush->style = logbrush->lbStyle;
|
||||
brush->colorref = logbrush->lbColor;
|
||||
brush->hatch = logbrush->lbHatch;
|
||||
|
||||
switch (logbrush->lbStyle)
|
||||
{
|
||||
case BS_SOLID: brush->rects = solid_brush; break;
|
||||
case BS_NULL: brush->rects = null_brush; break;
|
||||
case BS_HATCHED: brush->rects = pattern_brush; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* dibdrv_SelectBrush
|
||||
*/
|
||||
|
@ -1936,55 +1855,129 @@ HBRUSH dibdrv_SelectBrush( PHYSDEV dev, HBRUSH hbrush, const struct brush_patter
|
|||
{
|
||||
PHYSDEV next = GET_NEXT_PHYSDEV( dev, pSelectBrush );
|
||||
dibdrv_physdev *pdev = get_dibdrv_pdev(dev);
|
||||
dib_brush *brush = &pdev->brush;
|
||||
LOGBRUSH logbrush;
|
||||
|
||||
TRACE("(%p, %p)\n", dev, hbrush);
|
||||
|
||||
free_pattern_brush( brush );
|
||||
|
||||
if (pattern) /* pattern brush */
|
||||
{
|
||||
brush->rects = pattern_brush;
|
||||
brush->style = BS_DIBPATTERN;
|
||||
brush->pattern = *pattern;
|
||||
/* brush is actually selected only when it's used */
|
||||
|
||||
return next->funcs->pSelectBrush( next, hbrush, pattern );
|
||||
}
|
||||
|
||||
GetObjectW( hbrush, sizeof(logbrush), &logbrush );
|
||||
|
||||
if (hbrush == GetStockObject( DC_BRUSH ))
|
||||
logbrush.lbColor = GetDCBrushColor( dev->hdc );
|
||||
|
||||
brush->style = logbrush.lbStyle;
|
||||
|
||||
switch(logbrush.lbStyle)
|
||||
{
|
||||
case BS_SOLID:
|
||||
brush->colorref = logbrush.lbColor;
|
||||
brush->rects = solid_brush;
|
||||
break;
|
||||
|
||||
case BS_NULL:
|
||||
brush->rects = null_brush;
|
||||
break;
|
||||
|
||||
case BS_HATCHED:
|
||||
if(logbrush.lbHatch > HS_DIAGCROSS) return 0;
|
||||
brush->hatch = logbrush.lbHatch;
|
||||
brush->colorref = logbrush.lbColor;
|
||||
brush->rects = pattern_brush;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
select_brush( &pdev->brush, &logbrush, pattern );
|
||||
|
||||
return next->funcs->pSelectBrush( next, hbrush, pattern );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* dibdrv_SelectPen
|
||||
*/
|
||||
HPEN dibdrv_SelectPen( PHYSDEV dev, HPEN hpen, const struct brush_pattern *pattern )
|
||||
{
|
||||
PHYSDEV next = GET_NEXT_PHYSDEV( dev, pSelectPen );
|
||||
dibdrv_physdev *pdev = get_dibdrv_pdev(dev);
|
||||
LOGPEN logpen;
|
||||
LOGBRUSH logbrush;
|
||||
EXTLOGPEN *elp = NULL;
|
||||
|
||||
TRACE("(%p, %p)\n", dev, hpen);
|
||||
|
||||
if (!GetObjectW( hpen, sizeof(logpen), &logpen ))
|
||||
{
|
||||
/* must be an extended pen */
|
||||
INT size = GetObjectW( hpen, 0, NULL );
|
||||
|
||||
if (!size) return 0;
|
||||
|
||||
elp = HeapAlloc( GetProcessHeap(), 0, size );
|
||||
|
||||
GetObjectW( hpen, size, elp );
|
||||
logpen.lopnStyle = elp->elpPenStyle;
|
||||
logpen.lopnWidth.x = elp->elpWidth;
|
||||
/* cosmetic ext pens are always 1-pixel wide */
|
||||
if (!(logpen.lopnStyle & PS_GEOMETRIC)) logpen.lopnWidth.x = 0;
|
||||
|
||||
logbrush.lbStyle = elp->elpBrushStyle;
|
||||
logbrush.lbColor = elp->elpColor;
|
||||
logbrush.lbHatch = elp->elpHatch;
|
||||
}
|
||||
else
|
||||
{
|
||||
logbrush.lbStyle = BS_SOLID;
|
||||
logbrush.lbColor = logpen.lopnColor;
|
||||
logbrush.lbHatch = 0;
|
||||
}
|
||||
|
||||
pdev->pen_join = logpen.lopnStyle & PS_JOIN_MASK;
|
||||
pdev->pen_endcap = logpen.lopnStyle & PS_ENDCAP_MASK;
|
||||
pdev->pen_width = get_pen_device_width( pdev, logpen.lopnWidth.x );
|
||||
|
||||
if (hpen == GetStockObject( DC_PEN ))
|
||||
logbrush.lbColor = GetDCPenColor( dev->hdc );
|
||||
|
||||
set_dash_pattern( &pdev->pen_pattern, 0, NULL );
|
||||
select_brush( &pdev->pen_brush, &logbrush, pattern );
|
||||
|
||||
pdev->defer |= DEFER_PEN;
|
||||
|
||||
pdev->pen_style = logpen.lopnStyle & PS_STYLE_MASK;
|
||||
|
||||
switch (pdev->pen_style)
|
||||
{
|
||||
case PS_DASH:
|
||||
case PS_DOT:
|
||||
case PS_DASHDOT:
|
||||
case PS_DASHDOTDOT:
|
||||
if (logpen.lopnStyle & PS_GEOMETRIC)
|
||||
{
|
||||
if (pdev->pen_width > 1) break; /* not supported yet */
|
||||
pdev->pen_lines = dashed_pen_lines;
|
||||
pdev->pen_pattern = dash_patterns_geometric[pdev->pen_style - 1];
|
||||
pdev->defer &= ~DEFER_PEN;
|
||||
break;
|
||||
}
|
||||
if (pdev->pen_width == 1) /* wide cosmetic pens are not dashed */
|
||||
{
|
||||
pdev->pen_lines = dashed_pen_lines;
|
||||
pdev->pen_pattern = dash_patterns_cosmetic[pdev->pen_style - 1];
|
||||
pdev->defer &= ~DEFER_PEN;
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
case PS_SOLID:
|
||||
case PS_INSIDEFRAME:
|
||||
pdev->pen_lines = (pdev->pen_width == 1) ? solid_pen_lines : wide_pen_lines;
|
||||
pdev->defer &= ~DEFER_PEN;
|
||||
break;
|
||||
|
||||
case PS_NULL:
|
||||
pdev->pen_width = 0;
|
||||
pdev->pen_lines = null_pen_lines;
|
||||
pdev->defer &= ~DEFER_PEN;
|
||||
break;
|
||||
|
||||
case PS_ALTERNATE:
|
||||
pdev->pen_lines = dashed_pen_lines;
|
||||
pdev->pen_pattern = dash_patterns_geometric[PS_DOT - 1];
|
||||
pdev->defer &= ~DEFER_PEN;
|
||||
break;
|
||||
|
||||
case PS_USERSTYLE:
|
||||
if (pdev->pen_width > 1) break; /* not supported yet */
|
||||
pdev->pen_lines = dashed_pen_lines;
|
||||
set_dash_pattern( &pdev->pen_pattern, elp->elpNumEntries, elp->elpStyleEntry );
|
||||
if (!(logpen.lopnStyle & PS_GEOMETRIC)) scale_dash_pattern( &pdev->pen_pattern, 3 );
|
||||
pdev->defer &= ~DEFER_PEN;
|
||||
break;
|
||||
}
|
||||
|
||||
pdev->pen_uses_region = (logpen.lopnStyle & PS_GEOMETRIC || pdev->pen_width > 1);
|
||||
pdev->pen_is_ext = (elp != NULL);
|
||||
HeapFree( GetProcessHeap(), 0, elp );
|
||||
|
||||
return next->funcs->pSelectPen( next, hpen, pattern );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* dibdrv_SetDCBrushColor
|
||||
*/
|
||||
|
@ -2020,17 +2013,6 @@ BOOL brush_region( dibdrv_physdev *pdev, HRGN region )
|
|||
/* paint a region with the pen (note: the region can be modified) */
|
||||
BOOL pen_region( dibdrv_physdev *pdev, HRGN region )
|
||||
{
|
||||
struct clipped_rects clipped_rects;
|
||||
rop_mask color;
|
||||
DWORD pen_color = get_pixel_color( pdev, pdev->pen_colorref, TRUE );
|
||||
|
||||
if (pdev->clip) CombineRgn( region, region, pdev->clip, RGN_AND );
|
||||
|
||||
if (!get_clipped_rects( &pdev->dib, NULL, region, &clipped_rects )) return TRUE;
|
||||
|
||||
calc_rop_masks( GetROP2( pdev->dev.hdc ), pen_color, &color );
|
||||
pdev->dib.funcs->solid_rects( &pdev->dib, clipped_rects.count, clipped_rects.rects,
|
||||
color.and, color.xor );
|
||||
free_clipped_rects( &clipped_rects );
|
||||
return TRUE;
|
||||
return brush_rect( pdev, &pdev->pen_brush, NULL, region, GetROP2( pdev->dev.hdc ));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue