gdi32: Implement Arc, ArcTo, Chord, and Pie, using line segments for now.
This commit is contained in:
parent
92d5b41599
commit
ff31a448b3
|
@ -558,12 +558,12 @@ const struct gdi_dc_funcs dib_driver =
|
|||
NULL, /* pAbortPath */
|
||||
dibdrv_AlphaBlend, /* pAlphaBlend */
|
||||
NULL, /* pAngleArc */
|
||||
NULL, /* pArc */
|
||||
NULL, /* pArcTo */
|
||||
dibdrv_Arc, /* pArc */
|
||||
dibdrv_ArcTo, /* pArcTo */
|
||||
NULL, /* pBeginPath */
|
||||
dibdrv_BlendImage, /* pBlendImage */
|
||||
dibdrv_ChoosePixelFormat, /* pChoosePixelFormat */
|
||||
NULL, /* pChord */
|
||||
dibdrv_Chord, /* pChord */
|
||||
NULL, /* pCloseFigure */
|
||||
dibdrv_CopyBitmap, /* pCopyBitmap */
|
||||
NULL, /* pCreateBitmap */
|
||||
|
@ -627,7 +627,7 @@ const struct gdi_dc_funcs dib_driver =
|
|||
NULL, /* pOffsetWindowOrg */
|
||||
dibdrv_PaintRgn, /* pPaintRgn */
|
||||
dibdrv_PatBlt, /* pPatBlt */
|
||||
NULL, /* pPie */
|
||||
dibdrv_Pie, /* pPie */
|
||||
NULL, /* pPolyBezier */
|
||||
NULL, /* pPolyBezierTo */
|
||||
NULL, /* pPolyDraw */
|
||||
|
|
|
@ -110,8 +110,14 @@ typedef struct dibdrv_physdev
|
|||
|
||||
extern BOOL dibdrv_AlphaBlend( PHYSDEV dst_dev, struct bitblt_coords *dst,
|
||||
PHYSDEV src_dev, struct bitblt_coords *src, BLENDFUNCTION blend ) DECLSPEC_HIDDEN;
|
||||
extern BOOL dibdrv_Arc( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
|
||||
INT start_x, INT start_y, INT end_x, INT end_y ) DECLSPEC_HIDDEN;
|
||||
extern BOOL dibdrv_ArcTo( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
|
||||
INT start_x, INT start_y, INT end_x, INT end_y ) DECLSPEC_HIDDEN;
|
||||
extern DWORD dibdrv_BlendImage( PHYSDEV dev, BITMAPINFO *info, const struct gdi_image_bits *bits,
|
||||
struct bitblt_coords *src, struct bitblt_coords *dst, BLENDFUNCTION func ) DECLSPEC_HIDDEN;
|
||||
extern BOOL dibdrv_Chord( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
|
||||
INT start_x, INT start_y, INT end_x, INT end_y ) DECLSPEC_HIDDEN;
|
||||
extern BOOL dibdrv_Ellipse( PHYSDEV dev, INT left, INT top, INT right, INT bottom ) DECLSPEC_HIDDEN;
|
||||
extern BOOL dibdrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags,
|
||||
const RECT *rect, LPCWSTR str, UINT count, const INT *dx ) DECLSPEC_HIDDEN;
|
||||
|
@ -124,6 +130,8 @@ extern BOOL dibdrv_GradientFill( PHYSDEV dev, TRIVERTEX *vert_array, ULONG n
|
|||
extern BOOL dibdrv_LineTo( PHYSDEV dev, INT x, INT y ) DECLSPEC_HIDDEN;
|
||||
extern BOOL dibdrv_PatBlt( PHYSDEV dev, struct bitblt_coords *dst, DWORD rop ) DECLSPEC_HIDDEN;
|
||||
extern BOOL dibdrv_PaintRgn( PHYSDEV dev, HRGN hrgn ) DECLSPEC_HIDDEN;
|
||||
extern BOOL dibdrv_Pie( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
|
||||
INT start_x, INT start_y, INT end_x, INT end_y ) DECLSPEC_HIDDEN;
|
||||
extern BOOL dibdrv_PolyPolygon( PHYSDEV dev, const POINT *pt, const INT *counts, DWORD polygons ) DECLSPEC_HIDDEN;
|
||||
extern BOOL dibdrv_PolyPolyline( PHYSDEV dev, const POINT* pt, const DWORD* counts,
|
||||
DWORD polylines ) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -109,6 +109,199 @@ static int ellipse_first_quadrant( int width, int height, POINT *data )
|
|||
return pos;
|
||||
}
|
||||
|
||||
static int find_intersection( const POINT *points, int x, int y, int count )
|
||||
{
|
||||
int i;
|
||||
|
||||
if (y >= 0)
|
||||
{
|
||||
if (x >= 0) /* first quadrant */
|
||||
{
|
||||
for (i = 0; i < count; i++) if (points[i].x * y <= points[i].y * x) break;
|
||||
return i;
|
||||
}
|
||||
/* second quadrant */
|
||||
for (i = 0; i < count; i++) if (points[i].x * y < points[i].y * -x) break;
|
||||
return 2 * count - i;
|
||||
}
|
||||
if (x >= 0) /* fourth quadrant */
|
||||
{
|
||||
for (i = 0; i < count; i++) if (points[i].x * -y <= points[i].y * x) break;
|
||||
return 4 * count - i;
|
||||
}
|
||||
/* third quadrant */
|
||||
for (i = 0; i < count; i++) if (points[i].x * -y < points[i].y * -x) break;
|
||||
return 2 * count + i;
|
||||
}
|
||||
|
||||
static int get_arc_points( PHYSDEV dev, const RECT *rect, POINT start, POINT end, POINT *points )
|
||||
{
|
||||
int i, pos, count, start_pos, end_pos;
|
||||
int width = rect->right - rect->left;
|
||||
int height = rect->bottom - rect->top;
|
||||
|
||||
count = ellipse_first_quadrant( width, height, points );
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
points[i].x -= width / 2;
|
||||
points[i].y -= height / 2;
|
||||
}
|
||||
if (GetArcDirection( dev->hdc ) != AD_CLOCKWISE)
|
||||
{
|
||||
start.y = -start.y;
|
||||
end.y = -end.y;
|
||||
}
|
||||
start_pos = find_intersection( points, start.x, start.y, count );
|
||||
end_pos = find_intersection( points, end.x, end.y, count );
|
||||
if (end_pos <= start_pos) end_pos += 4 * count;
|
||||
|
||||
pos = count;
|
||||
if (GetArcDirection( dev->hdc ) == AD_CLOCKWISE)
|
||||
{
|
||||
for (i = start_pos; i < end_pos; i++, pos++)
|
||||
{
|
||||
switch ((i / count) % 4)
|
||||
{
|
||||
case 0:
|
||||
points[pos].x = rect->left + width/2 + points[i % count].x;
|
||||
points[pos].y = rect->top + height/2 + points[i % count].y;
|
||||
break;
|
||||
case 1:
|
||||
points[pos].x = rect->left + width/2 - points[count - 1 - i % count].x;
|
||||
points[pos].y = rect->top + height/2 + points[count - 1 - i % count].y;
|
||||
break;
|
||||
case 2:
|
||||
points[pos].x = rect->left + width/2 - points[i % count].x;
|
||||
points[pos].y = rect->top + height/2 - points[i % count].y;
|
||||
break;
|
||||
case 3:
|
||||
points[pos].x = rect->left + width/2 + points[count - 1 - i % count].x;
|
||||
points[pos].y = rect->top + height/2 - points[count - 1 - i % count].y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = start_pos; i < end_pos; i++, pos++)
|
||||
{
|
||||
switch ((i / count) % 4)
|
||||
{
|
||||
case 0:
|
||||
points[pos].x = rect->left + width/2 + points[i % count].x;
|
||||
points[pos].y = rect->top + height/2 - points[i % count].y;
|
||||
break;
|
||||
case 1:
|
||||
points[pos].x = rect->left + width/2 - points[count - 1 - i % count].x;
|
||||
points[pos].y = rect->top + height/2 - points[count - 1 - i % count].y;
|
||||
break;
|
||||
case 2:
|
||||
points[pos].x = rect->left + width/2 - points[i % count].x;
|
||||
points[pos].y = rect->top + height/2 + points[i % count].y;
|
||||
break;
|
||||
case 3:
|
||||
points[pos].x = rect->left + width/2 + points[count - 1 - i % count].x;
|
||||
points[pos].y = rect->top + height/2 + points[count - 1 - i % count].y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
memmove( points, points + count, (pos - count) * sizeof(POINT) );
|
||||
return pos - count;
|
||||
}
|
||||
|
||||
/* backend for arc functions; extra_lines is -1 for ArcTo, 0 for Arc, 1 for Chord, 2 for Pie */
|
||||
static BOOL draw_arc( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
|
||||
INT start_x, INT start_y, INT end_x, INT end_y, INT extra_lines )
|
||||
{
|
||||
dibdrv_physdev *pdev = get_dibdrv_pdev( dev );
|
||||
RECT rect;
|
||||
POINT pt[2], *points;
|
||||
int width, height, count;
|
||||
BOOL ret = TRUE;
|
||||
HRGN outline = 0, interior = 0;
|
||||
|
||||
if (!get_pen_device_rect( pdev, &rect, left, top, right, bottom )) return TRUE;
|
||||
|
||||
width = rect.right - rect.left;
|
||||
height = rect.bottom - rect.top;
|
||||
|
||||
pt[0].x = start_x;
|
||||
pt[0].y = start_y;
|
||||
pt[1].x = end_x;
|
||||
pt[1].y = end_y;
|
||||
LPtoDP( dev->hdc, pt, 2 );
|
||||
/* make them relative to the ellipse center */
|
||||
pt[0].x -= left + width / 2;
|
||||
pt[0].y -= top + height / 2;
|
||||
pt[1].x -= left + width / 2;
|
||||
pt[1].y -= top + height / 2;
|
||||
|
||||
points = HeapAlloc( GetProcessHeap(), 0, (width + height) * 3 * sizeof(*points) );
|
||||
if (!points) return FALSE;
|
||||
|
||||
if (extra_lines == -1)
|
||||
{
|
||||
GetCurrentPositionEx( dev->hdc, points );
|
||||
LPtoDP( dev->hdc, points, 1 );
|
||||
count = 1 + get_arc_points( dev, &rect, pt[0], pt[1], points + 1 );
|
||||
}
|
||||
else count = get_arc_points( dev, &rect, pt[0], pt[1], points );
|
||||
|
||||
if (extra_lines == 2)
|
||||
{
|
||||
points[count].x = rect.left + width / 2;
|
||||
points[count].y = rect.top + height / 2;
|
||||
count++;
|
||||
}
|
||||
if (count < 2)
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, points );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (pdev->pen_uses_region && !(outline = CreateRectRgn( 0, 0, 0, 0 )))
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, points );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (pdev->brush.style != BS_NULL && extra_lines > 0 &&
|
||||
!(interior = CreatePolygonRgn( points, count, WINDING )))
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, points );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (pdev->pen_uses_region) outline = CreateRectRgn( 0, 0, 0, 0 );
|
||||
|
||||
/* if not using a region, paint the interior first so the outline can overlap it */
|
||||
if (interior && !outline)
|
||||
{
|
||||
ret = brush_region( pdev, interior );
|
||||
DeleteObject( interior );
|
||||
interior = 0;
|
||||
}
|
||||
|
||||
reset_dash_origin( pdev );
|
||||
pdev->pen_lines( pdev, count, points, extra_lines > 0, outline );
|
||||
|
||||
if (interior)
|
||||
{
|
||||
CombineRgn( interior, interior, outline, RGN_DIFF );
|
||||
ret = brush_region( pdev, interior );
|
||||
DeleteObject( interior );
|
||||
}
|
||||
if (outline)
|
||||
{
|
||||
if (ret) ret = pen_region( pdev, outline );
|
||||
DeleteObject( outline );
|
||||
}
|
||||
HeapFree( GetProcessHeap(), 0, points );
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Intensities of the 17 glyph levels when drawn with text component of 0xff on a
|
||||
black bkgnd. [A log-log plot of these data gives: y = 77.05 * x^0.4315]. */
|
||||
static const BYTE ramp[17] =
|
||||
|
@ -451,6 +644,33 @@ done:
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* dibdrv_Arc
|
||||
*/
|
||||
BOOL dibdrv_Arc( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
|
||||
INT start_x, INT start_y, INT end_x, INT end_y )
|
||||
{
|
||||
return draw_arc( dev, left, top, right, bottom, start_x, start_y, end_x, end_y, 0 );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* dibdrv_ArcTo
|
||||
*/
|
||||
BOOL dibdrv_ArcTo( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
|
||||
INT start_x, INT start_y, INT end_x, INT end_y )
|
||||
{
|
||||
return draw_arc( dev, left, top, right, bottom, start_x, start_y, end_x, end_y, -1 );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* dibdrv_Chord
|
||||
*/
|
||||
BOOL dibdrv_Chord( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
|
||||
INT start_x, INT start_y, INT end_x, INT end_y )
|
||||
{
|
||||
return draw_arc( dev, left, top, right, bottom, start_x, start_y, end_x, end_y, 1 );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* dibdrv_Ellipse
|
||||
*/
|
||||
|
@ -881,6 +1101,15 @@ BOOL dibdrv_RoundRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* dibdrv_Pie
|
||||
*/
|
||||
BOOL dibdrv_Pie( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
|
||||
INT start_x, INT start_y, INT end_x, INT end_y )
|
||||
{
|
||||
return draw_arc( dev, left, top, right, bottom, start_x, start_y, end_x, end_y, 2 );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* dibdrv_SetPixel
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue