summaryrefslogtreecommitdiff
path: root/src/gdiplus/cdwinp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gdiplus/cdwinp.cpp')
-rw-r--r--src/gdiplus/cdwinp.cpp445
1 files changed, 441 insertions, 4 deletions
diff --git a/src/gdiplus/cdwinp.cpp b/src/gdiplus/cdwinp.cpp
index ea14628..a8d3f9c 100644
--- a/src/gdiplus/cdwinp.cpp
+++ b/src/gdiplus/cdwinp.cpp
@@ -51,10 +51,10 @@ void cdwpShowStatus(const char* title, Status status)
void cdwpKillCanvas(cdCtxCanvas* ctxcanvas)
{
if (ctxcanvas->clip_poly) delete[] ctxcanvas->clip_poly;
+ if (ctxcanvas->clip_fpoly) delete[] ctxcanvas->clip_fpoly;
if (ctxcanvas->clip_region) delete ctxcanvas->clip_region;
if (ctxcanvas->new_region) delete ctxcanvas->new_region;
if (ctxcanvas->font) delete ctxcanvas->font;
- if (ctxcanvas->wdpoly) delete ctxcanvas->wdpoly;
delete ctxcanvas->fillBrush;
delete ctxcanvas->lineBrush;
@@ -245,7 +245,10 @@ static void sClipPoly(cdCtxCanvas* ctxcanvas)
GraphicsPath path;
path.SetFillMode(ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
- path.AddPolygon(ctxcanvas->clip_poly, ctxcanvas->clip_poly_n);
+ if (ctxcanvas->clip_fpoly)
+ path.AddPolygon(ctxcanvas->clip_fpoly, ctxcanvas->clip_poly_n);
+ else
+ path.AddPolygon(ctxcanvas->clip_poly, ctxcanvas->clip_poly_n);
ctxcanvas->clip_region = new Region(&path);
ctxcanvas->graphics->SetClip(ctxcanvas->clip_region);
@@ -572,6 +575,12 @@ static void cdline(cdCtxCanvas* ctxcanvas, int x1, int y1, int x2, int y2)
ctxcanvas->dirty = 1;
}
+static void cdfline(cdCtxCanvas* ctxcanvas, double x1, double y1, double x2, double y2)
+{
+ ctxcanvas->graphics->DrawLine(ctxcanvas->linePen, (REAL)x1, (REAL)y1, (REAL)x2, (REAL)y2);
+ ctxcanvas->dirty = 1;
+}
+
static void cdrect(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax)
{
Rect rect(xmin, ymin, xmax-xmin, ymax-ymin); // in this case Size = Max - Min
@@ -579,6 +588,13 @@ static void cdrect(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int yma
ctxcanvas->dirty = 1;
}
+static void cdfrect(cdCtxCanvas* ctxcanvas, double xmin, double xmax, double ymin, double ymax)
+{
+ RectF rect((REAL)xmin, (REAL)ymin, (REAL)(xmax-xmin), (REAL)(ymax-ymin)); // in this case Size = Max - Min
+ ctxcanvas->graphics->DrawRectangle(ctxcanvas->linePen, rect);
+ ctxcanvas->dirty = 1;
+}
+
static void cdbox(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax)
{
Rect rect(xmin, ymin, xmax-xmin+1, ymax-ymin+1);
@@ -594,6 +610,21 @@ static void cdbox(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax
}
}
+static void cdfbox(cdCtxCanvas* ctxcanvas, double xmin, double xmax, double ymin, double ymax)
+{
+ RectF rect((REAL)xmin, (REAL)ymin, (REAL)(xmax-xmin+1), (REAL)(ymax-ymin+1));
+ if (ctxcanvas->canvas->new_region)
+ {
+ Region region(rect);
+ sCombineRegion(ctxcanvas, region);
+ }
+ else
+ {
+ ctxcanvas->graphics->FillRectangle(ctxcanvas->fillBrush, rect);
+ ctxcanvas->dirty = 1;
+ }
+}
+
static void cdwpFixAngles(cdCtxCanvas* ctxcanvas, double *angle1, double *angle2)
{
if (ctxcanvas->canvas->invert_yaxis)
@@ -617,6 +648,19 @@ static void cdarc(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double a
ctxcanvas->dirty = 1;
}
+static void cdfarc(cdCtxCanvas* ctxcanvas, double xc, double yc, double w, double h, double angle1, double angle2)
+{
+ RectF rect((REAL)(xc - w/2.0), (REAL)(yc - h/2.0), (REAL)w, (REAL)h);
+ if (angle1 == 0 && angle2 == 360)
+ ctxcanvas->graphics->DrawEllipse(ctxcanvas->linePen, rect);
+ else
+ {
+ cdwpFixAngles(ctxcanvas, &angle1, &angle2);
+ ctxcanvas->graphics->DrawArc(ctxcanvas->linePen, rect, (REAL)angle1, (REAL)(angle2-angle1));
+ }
+ ctxcanvas->dirty = 1;
+}
+
static void cdsector(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2)
{
Rect rect(xc - w/2, yc - h/2, w, h);
@@ -653,6 +697,42 @@ static void cdsector(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, doubl
}
}
+static void cdfsector(cdCtxCanvas* ctxcanvas, double xc, double yc, double w, double h, double angle1, double angle2)
+{
+ RectF rect((REAL)(xc - w/2.0), (REAL)(yc - h/2.0), (REAL)w, (REAL)h);
+ if (ctxcanvas->canvas->new_region)
+ {
+ GraphicsPath path;
+ if (angle1==0 && angle2==360)
+ path.AddEllipse(rect);
+ else
+ {
+ cdwpFixAngles(ctxcanvas, &angle1, &angle2);
+ path.AddPie(rect, (REAL)angle1, (REAL)(angle2-angle1));
+ }
+ Region region(&path);
+ sCombineRegion(ctxcanvas, region);
+ }
+ else
+ {
+ // complete the remaining pixels using an Arc
+ Pen pen(ctxcanvas->fillBrush);
+
+ if (angle1==0 && angle2==360)
+ {
+ ctxcanvas->graphics->FillEllipse(ctxcanvas->fillBrush, rect);
+ ctxcanvas->graphics->DrawEllipse(&pen, rect);
+ }
+ else
+ {
+ cdwpFixAngles(ctxcanvas, &angle1, &angle2);
+ ctxcanvas->graphics->FillPie(ctxcanvas->fillBrush, rect, (REAL)angle1, (REAL)(angle2-angle1));
+ ctxcanvas->graphics->DrawArc(&pen, rect, (REAL)angle1, (REAL)(angle2-angle1));
+ }
+ ctxcanvas->dirty = 1;
+ }
+}
+
static void cdchord(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double angle1, double angle2)
{
Rect rect(xc - w/2, yc - h/2, w, h);
@@ -687,10 +767,135 @@ static void cdchord(cdCtxCanvas* ctxcanvas, int xc, int yc, int w, int h, double
}
}
+static void cdfchord(cdCtxCanvas* ctxcanvas, double xc, double yc, double w, double h, double angle1, double angle2)
+{
+ RectF rect((REAL)(xc - w/2.0), (REAL)(yc - h/2.0), (REAL)w, (REAL)h);
+ if (ctxcanvas->canvas->new_region)
+ {
+ GraphicsPath path;
+ if (angle1==0 && angle2==360)
+ path.AddEllipse(rect);
+ else
+ {
+ cdwpFixAngles(ctxcanvas, &angle1, &angle2);
+ path.AddArc(rect, (REAL)angle1, (REAL)(angle2-angle1));
+ path.CloseFigure();
+ }
+ Region region(&path);
+ sCombineRegion(ctxcanvas, region);
+ }
+ else
+ {
+ if (angle1==0 && angle2==360)
+ ctxcanvas->graphics->FillEllipse(ctxcanvas->fillBrush, rect);
+ else
+ {
+ GraphicsPath path;
+ cdwpFixAngles(ctxcanvas, &angle1, &angle2);
+ path.AddArc(rect, (REAL)angle1, (REAL)(angle2-angle1));
+ ctxcanvas->graphics->FillPath(ctxcanvas->fillBrush, &path);
+ }
+ Pen pen(ctxcanvas->fillBrush); // complete the remaining pixels using an Arc
+ ctxcanvas->graphics->DrawArc(&pen, rect, (REAL)angle1, (REAL)(angle2-angle1));
+ ctxcanvas->dirty = 1;
+ }
+}
+
static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n)
{
- switch( mode )
+ switch (mode)
{
+ case CD_PATH:
+ {
+ int p, i, current_x = 0, current_y = 0;
+ GraphicsPath* graphics_path;
+ PointF lastPoint;
+
+ /* starts a new path */
+ graphics_path = new GraphicsPath(ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
+
+ i = 0;
+ for (p=0; p<ctxcanvas->canvas->path_n; p++)
+ {
+ switch(ctxcanvas->canvas->path[p])
+ {
+ case CD_PATH_NEW:
+ graphics_path->Reset();
+ graphics_path->SetFillMode(ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
+ break;
+ case CD_PATH_MOVETO:
+ if (i+1 > n) break;
+ current_x = poly[i].x;
+ current_y = poly[i].y;
+ i++;
+ break;
+ case CD_PATH_LINETO:
+ if (i+1 > n) break;
+ graphics_path->AddLine(current_x, current_y, poly[i].x, poly[i].y);
+ current_x = poly[i].x;
+ current_y = poly[i].y;
+ i++;
+ break;
+ case CD_PATH_ARC:
+ {
+ int xc, yc, w, h;
+ double a1, a2;
+
+ if (i+3 > n) break;
+
+ xc = poly[i].x,
+ yc = poly[i].y,
+ w = poly[i+1].x,
+ h = poly[i+1].y,
+ a1 = poly[i+2].x/1000.0,
+ a2 = poly[i+2].y/1000.0;
+
+ Rect rect(xc - w/2, yc - h/2, w, h);
+ if (a1 == 0 && a2 == 360)
+ graphics_path->AddEllipse(rect);
+ else
+ {
+ cdwpFixAngles(ctxcanvas, &a1, &a2);
+ graphics_path->AddArc(rect, (REAL)a1, (REAL)(a2-a1));
+ }
+
+ graphics_path->GetLastPoint(&lastPoint);
+ current_x = (int)lastPoint.X;
+ current_y = (int)lastPoint.Y;
+
+ i += 3;
+ }
+ break;
+ case CD_PATH_CURVETO:
+ if (i+3 > n) break;
+ graphics_path->AddBezier(current_x, current_y, poly[i].x, poly[i].y, poly[i+1].x, poly[i+1].y, poly[i+2].x, poly[i+2].y);
+ graphics_path->GetLastPoint(&lastPoint);
+ current_x = (int)lastPoint.X;
+ current_y = (int)lastPoint.Y;
+ i += 3;
+ break;
+ case CD_PATH_CLOSE:
+ graphics_path->CloseFigure();
+ break;
+ case CD_PATH_FILL:
+ ctxcanvas->graphics->FillPath(ctxcanvas->fillBrush, graphics_path);
+ break;
+ case CD_PATH_STROKE:
+ ctxcanvas->graphics->DrawPath(ctxcanvas->linePen, graphics_path);
+ break;
+ case CD_PATH_FILLSTROKE:
+ ctxcanvas->graphics->FillPath(ctxcanvas->fillBrush, graphics_path);
+ ctxcanvas->graphics->DrawPath(ctxcanvas->linePen, graphics_path);
+ break;
+ case CD_PATH_CLIP:
+ ctxcanvas->graphics->SetClip(graphics_path, CombineModeIntersect);
+ break;
+ }
+ }
+
+ delete graphics_path;
+ break;
+ }
case CD_BEZIER:
if (n < 4) return;
ctxcanvas->graphics->DrawBeziers(ctxcanvas->linePen, (Point*)poly, n);
@@ -749,6 +954,11 @@ static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n)
if (ctxcanvas->clip_poly)
delete[] ctxcanvas->clip_poly;
+ if (ctxcanvas->clip_fpoly)
+ {
+ delete[] ctxcanvas->clip_fpoly;
+ ctxcanvas->clip_fpoly = NULL;
+ }
ctxcanvas->clip_poly = new Point [n];
@@ -780,6 +990,223 @@ static void cdpoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n)
ctxcanvas->dirty = 1;
}
+static PointF* sPolyToFloat(cdfPoint* poly, int n)
+{
+ PointF* fpoly = new PointF[n+1];
+
+ for (int i = 0; i < n; i++)
+ {
+ fpoly[i].X = (REAL)poly[i].x;
+ fpoly[i].Y = (REAL)poly[i].y;
+ }
+
+ return fpoly;
+}
+
+static void cdfpoly(cdCtxCanvas* ctxcanvas, int mode, cdfPoint* poly, int n)
+{
+ PointF* fpoly = NULL;
+
+ switch (mode)
+ {
+ case CD_PATH:
+ {
+ int p, i;
+ double current_x = 0, current_y = 0;
+ GraphicsPath* graphics_path;
+ PointF lastPoint;
+
+ /* starts a new path */
+ graphics_path = new GraphicsPath(ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
+
+ i = 0;
+ for (p=0; p<ctxcanvas->canvas->path_n; p++)
+ {
+ switch(ctxcanvas->canvas->path[p])
+ {
+ case CD_PATH_NEW:
+ graphics_path->Reset();
+ graphics_path->SetFillMode(ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
+ break;
+ case CD_PATH_MOVETO:
+ if (i+1 > n) break;
+ current_x = poly[i].x;
+ current_y = poly[i].y;
+ i++;
+ break;
+ case CD_PATH_LINETO:
+ if (i+1 > n) break;
+ graphics_path->AddLine((REAL)current_x, (REAL)current_y, (REAL)poly[i].x, (REAL)poly[i].y);
+ current_x = poly[i].x;
+ current_y = poly[i].y;
+ i++;
+ break;
+ case CD_PATH_ARC:
+ {
+ double xc, yc, w, h;
+ double a1, a2;
+
+ if (i+3 > n) break;
+
+ xc = poly[i].x,
+ yc = poly[i].y,
+ w = poly[i+1].x,
+ h = poly[i+1].y,
+ a1 = poly[i+2].x,
+ a2 = poly[i+2].y;
+
+ RectF rect((REAL)(xc - w/2.0), (REAL)(yc - h/2.0), (REAL)w, (REAL)h);
+ if (a1 == 0 && a2 == 360)
+ graphics_path->AddEllipse(rect);
+ else
+ {
+ cdwpFixAngles(ctxcanvas, &a1, &a2);
+ graphics_path->AddArc(rect, (REAL)a1, (REAL)(a2-a1));
+ }
+
+ graphics_path->GetLastPoint(&lastPoint);
+ current_x = lastPoint.X;
+ current_y = lastPoint.Y;
+
+ i += 3;
+ }
+ break;
+ case CD_PATH_CURVETO:
+ if (i+3 > n) break;
+ graphics_path->AddBezier((REAL)current_x, (REAL)current_y, (REAL)poly[i].x, (REAL)poly[i].y, (REAL)poly[i+1].x, (REAL)poly[i+1].y, (REAL)poly[i+2].x, (REAL)poly[i+2].y);
+ graphics_path->GetLastPoint(&lastPoint);
+ current_x = lastPoint.X;
+ current_y = lastPoint.Y;
+ i += 3;
+ break;
+ case CD_PATH_CLOSE:
+ graphics_path->CloseFigure();
+ break;
+ case CD_PATH_FILL:
+ ctxcanvas->graphics->FillPath(ctxcanvas->fillBrush, graphics_path);
+ break;
+ case CD_PATH_STROKE:
+ ctxcanvas->graphics->DrawPath(ctxcanvas->linePen, graphics_path);
+ break;
+ case CD_PATH_FILLSTROKE:
+ ctxcanvas->graphics->FillPath(ctxcanvas->fillBrush, graphics_path);
+ ctxcanvas->graphics->DrawPath(ctxcanvas->linePen, graphics_path);
+ break;
+ case CD_PATH_CLIP:
+ ctxcanvas->graphics->SetClip(graphics_path, CombineModeIntersect);
+ break;
+ }
+ }
+
+ delete graphics_path;
+ break;
+ }
+ case CD_BEZIER:
+ if (n < 4) return;
+ fpoly = sPolyToFloat(poly, n);
+ ctxcanvas->graphics->DrawBeziers(ctxcanvas->linePen, (PointF*)fpoly, n);
+ break;
+ case CD_FILLSPLINE:
+ if (n < 4) return;
+ fpoly = sPolyToFloat(poly, n);
+ if (ctxcanvas->canvas->new_region)
+ {
+ GraphicsPath path(ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
+ path.AddClosedCurve((PointF*)fpoly, n);
+ Region region(&path);
+ sCombineRegion(ctxcanvas, region);
+ }
+ else
+ ctxcanvas->graphics->FillClosedCurve(ctxcanvas->fillBrush, (PointF*)fpoly, n);
+ break;
+ case CD_SPLINE:
+ if (n < 4) return;
+ fpoly = sPolyToFloat(poly, n);
+ ctxcanvas->graphics->DrawClosedCurve(ctxcanvas->linePen, (PointF*)fpoly, n);
+ break;
+ case CD_CLOSED_LINES:
+ poly[n].x = poly[0].x;
+ poly[n].y = poly[0].y;
+ n++;
+ /* continue */
+ case CD_OPEN_LINES:
+ fpoly = sPolyToFloat(poly, n);
+ ctxcanvas->graphics->DrawLines(ctxcanvas->linePen, (PointF*)fpoly, n);
+ break;
+ case CD_FILLGRADIENT:
+ {
+ int count = n;
+ PathGradientBrush* brush = new PathGradientBrush((PointF*)fpoly, n);
+ fpoly = sPolyToFloat(poly, n);
+ brush->SetSurroundColors(ctxcanvas->pathGradient, &count);
+ brush->SetCenterColor(ctxcanvas->pathGradient[n]);
+ ctxcanvas->graphics->FillPolygon(brush, (PointF*)fpoly, n, ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
+ delete brush;
+ }
+ break;
+ case CD_FILL:
+ poly[n].x = poly[0].x;
+ poly[n].y = poly[0].y;
+ n++;
+ fpoly = sPolyToFloat(poly, n);
+ if (ctxcanvas->canvas->new_region)
+ {
+ GraphicsPath path(ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
+ path.AddPolygon((PointF*)fpoly, n);
+ Region region(&path);
+ sCombineRegion(ctxcanvas, region);
+ }
+ else
+ ctxcanvas->graphics->FillPolygon(ctxcanvas->fillBrush, (PointF*)fpoly, n, ctxcanvas->canvas->fill_mode==CD_EVENODD?FillModeAlternate:FillModeWinding);
+ break;
+ case CD_CLIP:
+ poly[n].x = poly[0].x;
+ poly[n].y = poly[0].y;
+ n++;
+
+ if (ctxcanvas->clip_fpoly)
+ delete[] ctxcanvas->clip_fpoly;
+ if (ctxcanvas->clip_poly)
+ {
+ delete[] ctxcanvas->clip_poly;
+ ctxcanvas->clip_poly = NULL;
+ }
+
+ ctxcanvas->clip_fpoly = new PointF [n];
+
+ cdfPoint* pnt = poly;
+ int t = n;
+ int nc = 1;
+
+ ctxcanvas->clip_fpoly[0].X = (REAL)pnt->x;
+ ctxcanvas->clip_fpoly[0].Y = (REAL)pnt->y;
+ pnt++;
+
+ for (int i = 1; i < t-1; i++, pnt++)
+ {
+ if (!(((REAL)pnt->x == ctxcanvas->clip_fpoly[nc-1].X && pnt->x == (pnt + 1)->x) ||
+ ((REAL)pnt->y == ctxcanvas->clip_fpoly[nc-1].Y && pnt->y == (pnt + 1)->y)))
+ {
+ ctxcanvas->clip_fpoly[nc].X = (REAL)pnt->x;
+ ctxcanvas->clip_fpoly[nc].Y = (REAL)pnt->y;
+ nc++;
+ }
+ }
+
+ ctxcanvas->clip_poly_n = nc;
+
+ if (ctxcanvas->canvas->clip_mode == CD_CLIPPOLYGON)
+ sClipPoly(ctxcanvas);
+
+ break;
+ }
+
+ if (fpoly)
+ delete[] fpoly;
+
+ ctxcanvas->dirty = 1;
+}
+
WCHAR* cdwpString2Unicode(const char* s, int len)
{
static WCHAR wstr[10240] = L"";
@@ -1654,7 +2081,7 @@ static cdCtxImage *cdcreateimage(cdCtxCanvas* ctxcanvas, int width, int height)
ctximage->h_mm = ctximage->h / ctximage->yres;
Graphics imggraphics(ctximage->bitmap);
- imggraphics.Clear(Color::White);
+ imggraphics.Clear(Color((ARGB)Color::White));
return ctximage;
}
@@ -2248,6 +2675,7 @@ cdCtxCanvas *cdwpCreateCanvas(cdCanvas* canvas, Graphics* graphics, int wtype)
canvas->invert_yaxis = 1;
ctxcanvas->clip_poly = NULL;
+ ctxcanvas->clip_fpoly = NULL;
ctxcanvas->clip_poly_n = 0;
ctxcanvas->clip_region = NULL;
ctxcanvas->new_region = NULL;
@@ -2303,6 +2731,7 @@ void cdwpInitTable(cdCanvas* canvas)
canvas->cxFlush = cdflush;
canvas->cxPixel = cdpixel;
+
canvas->cxLine = cdline;
canvas->cxPoly = cdpoly;
canvas->cxRect = cdrect;
@@ -2312,6 +2741,14 @@ void cdwpInitTable(cdCanvas* canvas)
canvas->cxChord = cdchord;
canvas->cxText = cdtext;
+ canvas->cxFLine = cdfline;
+ canvas->cxFPoly = cdfpoly;
+ canvas->cxFRect = cdfrect;
+ canvas->cxFBox = cdfbox;
+ canvas->cxFArc = cdfarc;
+ canvas->cxFSector = cdfsector;
+ canvas->cxFChord = cdfchord;
+
canvas->cxNewRegion = cdnewregion;
canvas->cxIsPointInRegion = cdispointinregion;
canvas->cxOffsetRegion = cdoffsetregion;