summaryrefslogtreecommitdiff
path: root/cd/src/sim
diff options
context:
space:
mode:
authorNicolas "Pixel" Noble <pixel@nobis-crew.org>2010-09-09 01:48:52 +0200
committerNicolas "Pixel" Noble <pixel@nobis-crew.org>2010-09-09 01:50:25 +0200
commite9a184546b18cf3b796bd560561f312934004c54 (patch)
treeaa785af9a8d03f8ce276c9e9ecec78397005ec22 /cd/src/sim
parent92efe73791d0998536042bfab5a1babc67d168c7 (diff)
Upgrading to CD 5.4 - and cleaning up.
Diffstat (limited to 'cd/src/sim')
-rwxr-xr-xcd/src/sim/sim.c53
-rwxr-xr-xcd/src/sim/sim.h6
-rwxr-xr-xcd/src/sim/sim_linepolyfill.c98
-rwxr-xr-xcd/src/sim/sim_other.c411
-rwxr-xr-xcd/src/sim/sim_primitives.c1562
-rwxr-xr-xcd/src/sim/truetype.h46
6 files changed, 1377 insertions, 799 deletions
diff --git a/cd/src/sim/sim.c b/cd/src/sim/sim.c
index 3e4ccf1..839e4ff 100755
--- a/cd/src/sim/sim.c
+++ b/cd/src/sim/sim.c
@@ -88,7 +88,7 @@ void simFillHorizLine(cdSimulation* simulation, int xmin, int y, int xmax)
switch(canvas->interior_style)
{
case CD_SOLID:
- simulation->SolidLine(canvas, xmin,y,xmax);
+ simulation->SolidLine(canvas, xmin,y,xmax, canvas->foreground);
break;
case CD_PATTERN:
simulation->PatternLine(canvas, xmin,xmax,y,canvas->pattern_w,
@@ -106,10 +106,20 @@ void simFillHorizLine(cdSimulation* simulation, int xmin, int y, int xmax)
}
}
-static void simSolidLine(cdCanvas* canvas, int xmin, int y, int xmax)
+void simFillHorizBox(cdSimulation* simulation, int xmin, int xmax, int ymin, int ymax)
{
- /* cdpolySIM and cdboxSIM will set line attributes so this can work */
- canvas->cxLine(canvas->ctxcanvas, xmin, y, xmax, y);
+ int y;
+ for(y=ymin;y<=ymax;y++)
+ simFillHorizLine(simulation, xmin, y, xmax);
+}
+
+static void simSolidLine(cdCanvas* canvas, int xmin, int y, int xmax, long color)
+{
+ int x;
+ for (x = xmin; x <= xmax; x++)
+ {
+ canvas->cxPixel(canvas->ctxcanvas, x,y,color);
+ }
}
static void simPatternLine(cdCanvas* canvas, int xmin, int xmax, int y, int pw, const long *pattern)
@@ -117,12 +127,10 @@ static void simPatternLine(cdCanvas* canvas, int xmin, int xmax, int y, int pw,
cdSimulation* simulation = canvas->simulation;
int x,i;
int xb;
- long curColor, old_color;
+ long curColor;
i = xmin % pw;
-
- old_color = canvas->foreground;
-
+
for (x = xmin; x <= xmax;)
{
if (i == pw)
@@ -142,13 +150,8 @@ static void simPatternLine(cdCanvas* canvas, int xmin, int xmax, int y, int pw,
if(xb==x-1)
canvas->cxPixel(canvas->ctxcanvas, xb,y,curColor);
else
- {
- cdCanvasSetForeground(canvas, curColor);
- simulation->SolidLine(canvas, xb,y,x-1);
- }
+ simulation->SolidLine(canvas, xb,y,x-1, curColor);
}
-
- cdCanvasSetForeground(canvas, old_color);
}
static void simStippleLine(cdCanvas* canvas, int xmin, int xmax, int y, int pw, const unsigned char *stipple)
@@ -165,7 +168,7 @@ static void simStippleLine(cdCanvas* canvas, int xmin, int xmax, int y, int pw,
if(opacity==CD_OPAQUE)
{
bgColor=canvas->background;
- cdCanvasSetForeground(canvas, fgColor);
+
for (x = xmin, i=xmin%pw ; x <= xmax;)
{
if(i==pw)
@@ -184,10 +187,10 @@ static void simStippleLine(cdCanvas* canvas, int xmin, int xmax, int y, int pw,
if(xb==x-1)
canvas->cxPixel(canvas->ctxcanvas, xb,y,fgColor);
else
- simulation->SolidLine(canvas, xb,y,x-1);
+ simulation->SolidLine(canvas, xb,y,x-1,fgColor);
}
}
- cdCanvasSetForeground(canvas, bgColor);
+
for (x = xmin, i=xmin%pw ; x <= xmax;)
{
if(i==pw)
@@ -206,13 +209,12 @@ static void simStippleLine(cdCanvas* canvas, int xmin, int xmax, int y, int pw,
if(xb==x-1)
canvas->cxPixel(canvas->ctxcanvas, xb,y,bgColor);
else
- simulation->SolidLine(canvas, xb,y,x-1);
+ simulation->SolidLine(canvas, xb,y,x-1,bgColor);
}
}
}
else
{
- cdCanvasSetForeground(canvas, fgColor);
for (x = xmin,i=xmin%pw; x <= xmax;)
{
xb=x;
@@ -229,11 +231,10 @@ static void simStippleLine(cdCanvas* canvas, int xmin, int xmax, int y, int pw,
if(xb==x-1)
canvas->cxPixel(canvas->ctxcanvas, xb,y,fgColor);
else
- simulation->SolidLine(canvas, xb,y,x-1);
+ simulation->SolidLine(canvas, xb,y,x-1,fgColor);
}
}
}
- cdCanvasSetForeground(canvas, fgColor);
}
static void simHatchLine(cdCanvas* canvas, int xmin, int xmax, int y, unsigned char hatch)
@@ -268,15 +269,11 @@ static void simHatchLine(cdCanvas* canvas, int xmin, int xmax, int y, unsigned c
if(xb==x)
canvas->cxPixel(canvas->ctxcanvas, xb,y,curColor);
else
- {
- cdCanvasSetForeground(canvas, curColor);
- simulation->SolidLine(canvas, xb,y,x);
- }
+ simulation->SolidLine(canvas, xb,y,x, curColor);
}
}
else
{
- cdCanvasSetForeground(canvas, fgColor);
for (x = xmin; x <= xmax; x++)
{
mask=(hatch&0x80)?1:0;
@@ -295,12 +292,10 @@ static void simHatchLine(cdCanvas* canvas, int xmin, int xmax, int y, unsigned c
if(xb==x)
canvas->cxPixel(canvas->ctxcanvas, xb,y,fgColor);
else
- simulation->SolidLine(canvas, xb,y,x);
+ simulation->SolidLine(canvas, xb,y,x,fgColor);
}
}
}
-
- cdCanvasSetForeground(canvas, fgColor);
}
cdSimulation* cdCreateSimulation(cdCanvas* canvas)
diff --git a/cd/src/sim/sim.h b/cd/src/sim/sim.h
index e98b030..2832391 100755
--- a/cd/src/sim/sim.h
+++ b/cd/src/sim/sim.h
@@ -18,7 +18,7 @@ struct _cdSimulation
int font_map_n;
/* horizontal line draw functions */
- void (*SolidLine)(cdCanvas* canvas, int xmin, int y, int xmax);
+ void (*SolidLine)(cdCanvas* canvas, int xmin, int y, int xmax, long color);
void (*PatternLine)(cdCanvas* canvas, int xmin, int xmax, int y, int pw, const long *pattern);
void (*StippleLine)(cdCanvas* canvas, int xmin, int xmax, int y, int pw, const unsigned char *stipple);
void (*HatchLine)(cdCanvas* canvas, int xmin, int xmax, int y, unsigned char hatch);
@@ -28,6 +28,7 @@ struct _cdSimulation
void simFillDrawAAPixel(cdCanvas *canvas, int x, int y, unsigned short alpha_weigth);
void simFillHorizLine(cdSimulation* simulation, int xmin, int y, int xmax);
+void simFillHorizBox(cdSimulation* simulation, int xmin, int xmax, int ymin, int ymax);
int simIsPointInPolyWind(cdPoint* poly, int n, int x, int y);
/* list of non-horizontal line segments */
@@ -49,10 +50,9 @@ void simPolyMakeSegments(simLineSegment *segments, int *n_seg, cdPoint* poly, in
void simPolyFill(cdSimulation* simulation, cdPoint* poly, int n);
void simLineThin(cdCanvas* canvas, int x1, int y1, int x2, int y2);
void simLineThick(cdCanvas* canvas, int x1, int y1, int x2, int y2);
+void simfLineThick(cdCanvas* canvas, double x1, double y1, double x2, double y2);
void simfLineThin(cdCanvas* canvas, double x1, double y1, double x2, double y2, int *last_xi_a, int *last_yi_a, int *last_xi_b, int *last_yi_b);
extern int simLineStyleNoReset;
-int simCalcEllipseNumSegments(cdCanvas* canvas, int xc, int yc, int width, int height);
-
#endif
diff --git a/cd/src/sim/sim_linepolyfill.c b/cd/src/sim/sim_linepolyfill.c
index 2454a00..f73b26f 100755
--- a/cd/src/sim/sim_linepolyfill.c
+++ b/cd/src/sim/sim_linepolyfill.c
@@ -712,13 +712,67 @@ void simLineThick(cdCanvas* canvas, int x1, int y1, int x2, int y2)
cdCanvasLineStyle(canvas, style);
}
+void simfLineThick(cdCanvas* canvas, double x1, double y1, double x2, double y2)
+{
+ const int interior = canvas->interior_style;
+ const int width = canvas->line_width;
+ const int style = canvas->line_style;
+
+ const double dx = x2-x1;
+ const double dy = y2-y1;
+
+ const double len = hypot(dx,dy);
+
+ const double dnx = dx/len;
+ const double dny = dy/len;
+
+ const double w1 = width/2.0;
+ const double w2 = width-w1;
+
+ const double n1x = w1*dny;
+ const double n1y = -w1*dnx;
+
+ const double n2x = -w2*dny;
+ const double n2y = w2*dnx;
+
+ const double p1x = x1 + n1x;
+ const double p1y = y1 + n1y;
+ const double p2x = x1 + n2x;
+ const double p2y = y1 + n2y;
+ const double p3x = p2x + dx;
+ const double p3y = p2y + dy;
+ const double p4x = p1x + dx;
+ const double p4y = p1y + dy;
+
+ cdPoint poly[4];
+
+ cdCanvasLineWidth(canvas, 1);
+ cdCanvasInteriorStyle(canvas, CD_SOLID);
+ cdCanvasLineStyle(canvas, CD_CONTINUOUS);
+
+ poly[0].x = _cdRound(p1x);
+ poly[0].y = _cdRound(p1y);
+ poly[1].x = _cdRound(p2x);
+ poly[1].y = _cdRound(p2y);
+ poly[2].x = _cdRound(p3x);
+ poly[2].y = _cdRound(p3y);
+ poly[3].x = _cdRound(p4x);
+ poly[3].y = _cdRound(p4y);
+
+ simPolyFill(canvas->simulation, poly, 4);
+
+ cdCanvasLineWidth(canvas, width);
+ cdCanvasInteriorStyle(canvas, interior);
+ cdCanvasLineStyle(canvas, style);
+}
+
void simLineThin(cdCanvas* canvas, int x1, int y1, int x2, int y2)
{
unsigned short ErrorInc, ErrorAcc;
unsigned short ErrorAccTemp, Weighting;
int DeltaX, DeltaY, XDir;
long aa_fgcolor;
- unsigned char alpha = cdAlpha(canvas->foreground), aa_alpha;
+ unsigned char alpha = cdAlpha(canvas->foreground), aa_alpha1, aa_alpha2;
int no_antialias = !(canvas->simulation->antialias);
unsigned short int ls;
long fgcolor = canvas->foreground;
@@ -840,11 +894,12 @@ void simLineThin(cdCanvas* canvas, int x1, int y1, int x2, int y2)
weighting for the paired pixel.
Combine the Weighting with the existing alpha,
When Weighting is zero alpha must be fully preserved. */
- aa_alpha = (unsigned char)(((255-Weighting) * alpha) / 255);
+ aa_alpha1 = (unsigned char)(((255-Weighting) * alpha) / 255);
+ aa_alpha2 = (unsigned char)((Weighting * alpha) / 255);
- aa_fgcolor = cdEncodeAlpha(fgcolor, aa_alpha);
+ aa_fgcolor = cdEncodeAlpha(fgcolor, aa_alpha1);
_cdLineDrawPixel(canvas, x1, y1, ls, aa_fgcolor);
- aa_fgcolor = cdEncodeAlpha(fgcolor, 255-aa_alpha);
+ aa_fgcolor = cdEncodeAlpha(fgcolor, aa_alpha2);
_cdLineDrawPixel(canvas, x1 + XDir, y1, ls, aa_fgcolor);
ls = simRotateLineStyle(ls);
}
@@ -891,11 +946,12 @@ void simLineThin(cdCanvas* canvas, int x1, int y1, int x2, int y2)
weighting for the paired pixel.
Combine the Weighting with the existing alpha,
When Weighting is zero alpha must be fully preserved. */
- aa_alpha = (unsigned char)(((255-Weighting) * alpha) / 255);
+ aa_alpha1 = (unsigned char)(((255-Weighting) * alpha) / 255);
+ aa_alpha2 = (unsigned char)((Weighting * alpha) / 255);
- aa_fgcolor = cdEncodeAlpha(fgcolor, aa_alpha);
+ aa_fgcolor = cdEncodeAlpha(fgcolor, aa_alpha1);
_cdLineDrawPixel(canvas, x1, y1, ls, aa_fgcolor);
- aa_fgcolor = cdEncodeAlpha(fgcolor, 255-aa_alpha);
+ aa_fgcolor = cdEncodeAlpha(fgcolor, aa_alpha2);
_cdLineDrawPixel(canvas, x1, y1+1, ls, aa_fgcolor);
ls = simRotateLineStyle(ls);
}
@@ -914,7 +970,7 @@ void simfLineThin(cdCanvas* canvas, double x1, double y1, double x2, double y2,
{
double DeltaX, DeltaY, a, b;
long aa_fgcolor;
- unsigned char alpha = cdAlpha(canvas->foreground), aa_alpha;
+ unsigned char alpha = cdAlpha(canvas->foreground), aa_alpha1, aa_alpha2;
int no_antialias = !(canvas->simulation->antialias);
int yi, xi, update_a = 1, update_b = 1;
unsigned short int ls;
@@ -975,11 +1031,12 @@ void simfLineThin(cdCanvas* canvas, double x1, double y1, double x2, double y2,
/* Combine the Weighting with the existing alpha,
When Weighting is zero alpha must be fully preserved. */
- aa_alpha = (unsigned char)((1.0-(x - xi)) * alpha);
+ aa_alpha1 = (unsigned char)((1.0-(x - xi)) * alpha);
+ aa_alpha2 = (unsigned char)((x - xi) * alpha);
if (no_antialias)
{
- if (aa_alpha > 128)
+ if (aa_alpha1 > 128)
_cdLineDrawPixel(canvas, xi, yi, ls, fgcolor)
else
_cdLineDrawPixel(canvas, xi+1, yi, ls, fgcolor)
@@ -999,7 +1056,7 @@ void simfLineThin(cdCanvas* canvas, double x1, double y1, double x2, double y2,
if ((xi != *last_xi_a || yi != *last_yi_a) &&
(xi != *last_xi_b || yi != *last_yi_b))
{
- aa_fgcolor = cdEncodeAlpha(fgcolor, aa_alpha);
+ aa_fgcolor = cdEncodeAlpha(fgcolor, aa_alpha1);
_cdLineDrawPixel(canvas, xi, yi, ls, aa_fgcolor);
if (yi == yi_last) /* one pixel only */
@@ -1009,7 +1066,7 @@ void simfLineThin(cdCanvas* canvas, double x1, double y1, double x2, double y2,
if ((xi+1 != *last_xi_a || yi != *last_yi_a) &&
(xi+1 != *last_xi_b || yi != *last_yi_b))
{
- aa_fgcolor = cdEncodeAlpha(fgcolor, 255-aa_alpha);
+ aa_fgcolor = cdEncodeAlpha(fgcolor, aa_alpha2);
_cdLineDrawPixel(canvas, xi+1, yi, ls, aa_fgcolor);
if (yi == yi_last) /* one pixel only */
@@ -1018,9 +1075,9 @@ void simfLineThin(cdCanvas* canvas, double x1, double y1, double x2, double y2,
}
else
{
- aa_fgcolor = cdEncodeAlpha(fgcolor, aa_alpha);
+ aa_fgcolor = cdEncodeAlpha(fgcolor, aa_alpha1);
_cdLineDrawPixel(canvas, xi, yi, ls, aa_fgcolor);
- aa_fgcolor = cdEncodeAlpha(fgcolor, 255-aa_alpha);
+ aa_fgcolor = cdEncodeAlpha(fgcolor, aa_alpha2);
_cdLineDrawPixel(canvas, xi+1, yi, ls, aa_fgcolor);
}
}
@@ -1061,11 +1118,12 @@ void simfLineThin(cdCanvas* canvas, double x1, double y1, double x2, double y2,
/* Combine the Weighting with the existing alpha,
When Weighting is zero alpha must be fully preserved. */
- aa_alpha = (unsigned char)((1.0-(y - yi)) * alpha);
+ aa_alpha1 = (unsigned char)((1.0-(y - yi)) * alpha);
+ aa_alpha2 = (unsigned char)((y - yi) * alpha);
if (no_antialias)
{
- if (aa_alpha > 128)
+ if (aa_alpha1 > 128)
_cdLineDrawPixel(canvas, xi, yi, ls, fgcolor)
else
_cdLineDrawPixel(canvas, xi, yi+1, ls, fgcolor)
@@ -1085,7 +1143,7 @@ void simfLineThin(cdCanvas* canvas, double x1, double y1, double x2, double y2,
if ((xi != *last_xi_a || yi != *last_yi_a) &&
(xi != *last_xi_b || yi != *last_yi_b))
{
- aa_fgcolor = cdEncodeAlpha(fgcolor, aa_alpha);
+ aa_fgcolor = cdEncodeAlpha(fgcolor, aa_alpha1);
_cdLineDrawPixel(canvas, xi, yi, ls, aa_fgcolor);
if (xi == xi_last) /* one pixel only */
@@ -1095,7 +1153,7 @@ void simfLineThin(cdCanvas* canvas, double x1, double y1, double x2, double y2,
if ((xi != *last_xi_a || yi+1 != *last_yi_a) &&
(xi != *last_xi_b || yi+1 != *last_yi_b))
{
- aa_fgcolor = cdEncodeAlpha(fgcolor, 255-aa_alpha);
+ aa_fgcolor = cdEncodeAlpha(fgcolor, aa_alpha2);
_cdLineDrawPixel(canvas, xi, yi+1, ls, aa_fgcolor);
if (xi == xi_last) /* one pixel only */
@@ -1104,9 +1162,9 @@ void simfLineThin(cdCanvas* canvas, double x1, double y1, double x2, double y2,
}
else
{
- aa_fgcolor = cdEncodeAlpha(fgcolor, aa_alpha);
+ aa_fgcolor = cdEncodeAlpha(fgcolor, aa_alpha1);
_cdLineDrawPixel(canvas, xi, yi, ls, aa_fgcolor);
- aa_fgcolor = cdEncodeAlpha(fgcolor, 255-aa_alpha);
+ aa_fgcolor = cdEncodeAlpha(fgcolor, aa_alpha2);
_cdLineDrawPixel(canvas, xi, yi+1, ls, aa_fgcolor);
}
}
diff --git a/cd/src/sim/sim_other.c b/cd/src/sim/sim_other.c
deleted file mode 100755
index 0954406..0000000
--- a/cd/src/sim/sim_other.c
+++ /dev/null
@@ -1,411 +0,0 @@
-/** \file
- * \brief Simulation that is independent of the Simulation Base Driver
- *
- * See Copyright Notice in cd.h
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include <memory.h>
-
-#include "cd.h"
-#include "cd_private.h"
-
-
-void cdSimMark(cdCanvas* canvas, int x, int y)
-{
- int oldinteriorstyle = canvas->interior_style;
- int oldlinestyle = canvas->line_style;
- int oldlinewidth = canvas->line_width;
- int size = canvas->mark_size;
- int half_size = size/2;
- int bottom = y-half_size;
- int top = y+half_size;
- int left = x-half_size;
- int right = x+half_size;
-
- if (canvas->interior_style != CD_SOLID &&
- (canvas->mark_type == CD_CIRCLE ||
- canvas->mark_type == CD_BOX ||
- canvas->mark_type == CD_DIAMOND))
- cdCanvasInteriorStyle(canvas, CD_SOLID);
-
- if (canvas->line_style != CD_CONTINUOUS &&
- (canvas->mark_type == CD_STAR ||
- canvas->mark_type == CD_PLUS ||
- canvas->mark_type == CD_X ||
- canvas->mark_type == CD_HOLLOW_BOX ||
- canvas->mark_type == CD_HOLLOW_CIRCLE ||
- canvas->mark_type == CD_HOLLOW_DIAMOND))
- cdCanvasLineStyle(canvas, CD_CONTINUOUS);
-
- if (canvas->line_width != 1 &&
- (canvas->mark_type == CD_STAR ||
- canvas->mark_type == CD_PLUS ||
- canvas->mark_type == CD_X ||
- canvas->mark_type == CD_HOLLOW_BOX ||
- canvas->mark_type == CD_HOLLOW_CIRCLE ||
- canvas->mark_type == CD_HOLLOW_DIAMOND))
- cdCanvasLineWidth(canvas, 1);
-
- switch (canvas->mark_type)
- {
- case CD_STAR:
- canvas->cxLine(canvas->ctxcanvas, left, bottom, right, top);
- canvas->cxLine(canvas->ctxcanvas, left, top, right, bottom);
- /* continue */
- case CD_PLUS:
- canvas->cxLine(canvas->ctxcanvas, left, y, right, y);
- canvas->cxLine(canvas->ctxcanvas, x, bottom, x, top);
- break;
- case CD_HOLLOW_CIRCLE:
- canvas->cxArc(canvas->ctxcanvas, x, y, size, size, 0, 360);
- break;
- case CD_HOLLOW_BOX:
- canvas->cxRect(canvas->ctxcanvas, left, right, bottom, top);
- break;
- case CD_HOLLOW_DIAMOND:
- canvas->cxLine(canvas->ctxcanvas, left, y, x, top);
- canvas->cxLine(canvas->ctxcanvas, x, top, right, y);
- canvas->cxLine(canvas->ctxcanvas, right, y, x, bottom);
- canvas->cxLine(canvas->ctxcanvas, x, bottom, left, y);
- break;
- case CD_X:
- canvas->cxLine(canvas->ctxcanvas, left, bottom, right, top);
- canvas->cxLine(canvas->ctxcanvas, left, top, right, bottom);
- break;
- case CD_CIRCLE:
- canvas->cxSector(canvas->ctxcanvas, x, y, size, size, 0, 360);
- break;
- case CD_BOX:
- canvas->cxBox(canvas->ctxcanvas, left, right, bottom, top);
- break;
- case CD_DIAMOND:
- {
- cdPoint poly[5];
- poly[0].x = left;
- poly[0].y = y;
- poly[1].x = x;
- poly[1].y = top;
- poly[2].x = right;
- poly[2].y = y;
- poly[3].x = x;
- poly[3].y = bottom;
- canvas->cxPoly(canvas->ctxcanvas, CD_FILL, poly, 4);
- }
- break;
- }
-
- if (canvas->interior_style != oldinteriorstyle &&
- (canvas->mark_type == CD_CIRCLE ||
- canvas->mark_type == CD_BOX ||
- canvas->mark_type == CD_DIAMOND))
- cdCanvasInteriorStyle(canvas, oldinteriorstyle);
-
- if (canvas->line_style != oldlinestyle &&
- (canvas->mark_type == CD_STAR ||
- canvas->mark_type == CD_PLUS ||
- canvas->mark_type == CD_X ||
- canvas->mark_type == CD_HOLLOW_BOX ||
- canvas->mark_type == CD_HOLLOW_CIRCLE ||
- canvas->mark_type == CD_HOLLOW_DIAMOND))
- cdCanvasLineStyle(canvas, oldlinestyle);
-
- if (canvas->line_width != oldlinewidth &&
- (canvas->mark_type == CD_STAR ||
- canvas->mark_type == CD_PLUS ||
- canvas->mark_type == CD_X ||
- canvas->mark_type == CD_HOLLOW_BOX ||
- canvas->mark_type == CD_HOLLOW_CIRCLE ||
- canvas->mark_type == CD_HOLLOW_DIAMOND))
- cdCanvasLineWidth(canvas, oldlinewidth);
-}
-
-/* Setup Bezier coefficient array once for each control polygon.
- */
-static void BezierForm(const cdPoint* p, cdfPoint* c)
-{
- int k;
- static int choose[4] = {1, 3, 3, 1};
- for (k = 0; k < 4; k++)
- {
- c[k].x = p[k].x * choose[k];
- c[k].y = p[k].y * choose[k];
- }
-}
-
-static void fBezierForm(const cdfPoint* p, cdfPoint* c)
-{
- int k;
- static int choose[4] = {1, 3, 3, 1};
- for (k = 0; k < 4; k++)
- {
- c[k].x = p[k].x * choose[k];
- c[k].y = p[k].y * choose[k];
- }
-}
-
-/* Return Point pt(t), t <= 0 <= 1 from C.
- * BezierForm must be called once for any given control polygon.
- */
-static void BezierCurve(const cdfPoint* c, cdfPoint *pt, double t)
-{
- int k;
- double t1, tt, u;
- cdfPoint b[4];
-
- u = t;
-
- b[0].x = c[0].x;
- b[0].y = c[0].y;
- for(k = 1; k < 4; k++)
- {
- b[k].x = c[k].x * u;
- b[k].y = c[k].y * u;
- u =u*t;
- }
-
- pt->x = b[3].x;
- pt->y = b[3].y;
- t1 = 1-t;
- tt = t1;
- for(k = 2; k >= 0; k--)
- {
- pt->x += b[k].x * tt;
- pt->y += b[k].y * tt;
- tt =tt*t1;
- }
-}
-
-static int BezierNumSegments(cdCanvas* canvas, const cdPoint* p)
-{
- int i, K, dx, dy, d,
- xmax = p[0].x,
- ymax = p[0].y,
- xmin = p[0].x,
- ymin = p[0].y;
-
- for (i = 1; i < 4; i++)
- {
- if (p[i].x > xmax)
- xmax = p[i].x;
- if (p[i].y > ymax)
- ymax = p[i].y;
- if (p[i].x < xmin)
- xmin = p[i].x;
- if (p[i].y < ymin)
- ymin = p[i].y;
- }
-
- if (canvas->use_matrix)
- {
- cdMatrixTransformPoint(canvas->matrix, xmin, ymin, &xmin, &ymin);
- cdMatrixTransformPoint(canvas->matrix, xmax, ymax, &xmax, &ymax);
- }
-
- /* diagonal of the bouding box */
- dx = (xmax-xmin);
- dy = (ymax-ymin);
- d = (int)(sqrt(dx*dx + dy*dy));
- K = d / 8;
- if (K < 8) K = 8;
- return K;
-}
-
-static int fBezierNumSegments(cdCanvas* canvas, const cdfPoint* p)
-{
- int i, K, d;
- double dx, dy,
- xmax = p[0].x,
- ymax = p[0].y,
- xmin = p[0].x,
- ymin = p[0].y;
-
- for (i = 1; i < 4; i++)
- {
- if (p[i].x > xmax)
- xmax = p[i].x;
- if (p[i].y > ymax)
- ymax = p[i].y;
- if (p[i].x < xmin)
- xmin = p[i].x;
- if (p[i].y < ymin)
- ymin = p[i].y;
- }
-
- /* diagonal of the bouding box */
- dx = (xmax-xmin);
- dy = (ymax-ymin);
- d = (int)(sqrt(dx*dx + dy*dy));
- K = d / 8;
- if (K < 8) K = 8;
- return K;
-}
-
-/* from sim.h */
-void simfLineThin(cdCanvas* canvas, double x1, double y1, double x2, double y2, int *last_xi_a, int *last_yi_a, int *last_xi_b, int *last_yi_b);
-
-/* Quick and Simple Bezier Curve Drawing --- Robert D. Miller
- * Graphics GEMS V */
-void cdSimPolyBezier(cdCanvas* canvas, const cdPoint* points, int n)
-{
- int i = 0, k, K, poly_max = 0;
- cdfPoint pt, prev_pt;
- cdfPoint bezier_control[4];
- cdPoint* poly = NULL;
- int use_poly = 0,
- last_xi_a = -65535,
- last_yi_a = -65535,
- last_xi_b = -65535,
- last_yi_b = -65535;
-
- /* Use special floating point anti-alias line draw when
- line_width==1, and NOT using cdlineSIM. */
- if (canvas->line_width > 1 || canvas->cxLine != cdlineSIM)
- use_poly = 1;
-
- n--; /* first n is 4 */
- while (n >= 3)
- {
- BezierForm(points+i, bezier_control);
- K = BezierNumSegments(canvas, points+i);
-
- if (use_poly && poly_max < K+1)
- {
- poly = realloc(poly, sizeof(cdPoint)*(K+1)); /* K+1 points */
- if (!poly) return;
- poly_max = K+1;
- }
-
- /* first segment */
- BezierCurve(bezier_control, &pt, 0);
- if (use_poly)
- {
- poly[0].x = _cdRound(pt.x);
- poly[0].y = _cdRound(pt.y);
- }
- else
- prev_pt = pt;
-
- for(k = 1; k < K+1; k++)
- {
- BezierCurve(bezier_control, &pt, (double)k/(double)K);
-
- if (use_poly)
- {
- poly[k].x = _cdRound(pt.x);
- poly[k].y = _cdRound(pt.y);
- }
- else
- {
- int old_use_matrix = canvas->use_matrix;
- double x1 = prev_pt.x,
- y1 = prev_pt.y,
- x2 = pt.x,
- y2 = pt.y;
-
- if (canvas->use_matrix && !canvas->invert_yaxis)
- {
- cdfMatrixTransformPoint(canvas->matrix, x1, y1, &x1, &y1);
- cdfMatrixTransformPoint(canvas->matrix, x2, y2, &x2, &y2);
- }
-
- /* must disable transformation here, because line simulation use cxPixel */
- canvas->use_matrix = 0;
-
- simfLineThin(canvas, x1, y1, x2, y2, &last_xi_a, &last_yi_a, &last_xi_b, &last_yi_b);
-
- canvas->use_matrix = old_use_matrix;
- prev_pt = pt;
- }
- }
-
- if (use_poly)
- canvas->cxPoly(canvas->ctxcanvas, CD_OPEN_LINES, poly, k);
-
- n -= 3; i += 3;
- }
-
- if (poly) free(poly);
-}
-
-void cdfSimPolyBezier(cdCanvas* canvas, const cdfPoint* points, int n)
-{
- int i = 0, k, K, poly_max = 0;
- cdfPoint pt;
- cdfPoint bezier_control[4];
- cdfPoint* poly = NULL;
-
- n--; /* first n is 4 */
- while (n >= 3)
- {
- fBezierForm(points+i, bezier_control);
- K = fBezierNumSegments(canvas, points+i);
-
- if (poly_max < K+1)
- {
- poly = realloc(poly, sizeof(cdfPoint)*(K+1)); /* K+1 points */
- if (!poly) return;
- poly_max = K+1;
- }
-
- /* first segment */
- BezierCurve(bezier_control, &pt, 0);
- poly[0].x = _cdRound(pt.x);
- poly[0].y = _cdRound(pt.y);
-
- for(k = 1; k < K+1; k++)
- {
- BezierCurve(bezier_control, &pt, (double)k/(double)K);
-
- poly[k].x = _cdRound(pt.x);
- poly[k].y = _cdRound(pt.y);
- }
-
- canvas->cxFPoly(canvas->ctxcanvas, CD_OPEN_LINES, poly, k);
- n -= 3; i += 3;
- }
-
- if (poly) free(poly);
-}
-
-void cdSimPutImageRectRGBA(cdCanvas* canvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
-{
- int size, i, j, dst, src, *fx, *fy, rw, rh;
- unsigned char *ar, *ag, *ab, al;
-
- size = w * h;
- ar = (unsigned char*)malloc(size*3);
- if (!ar) return;
- ag = ar + size;
- ab = ag + size;
-
- canvas->cxGetImageRGB(canvas->ctxcanvas, ar, ag, ab, x, y, w, h);
-
- rw = xmax-xmin+1;
- rh = ymax-ymin+1;
-
- fx = cdGetZoomTable(w, rw, xmin);
- fy = cdGetZoomTable(h, rh, ymin);
-
- for (j = 0; j < h; j++)
- {
- for (i = 0; i < w; i++)
- {
- dst = j * w + i;
- src = fy[j] * iw + fx[i];
- al = a[src];
- ar[dst] = CD_ALPHA_BLEND(r[src], ar[dst], al);
- ag[dst] = CD_ALPHA_BLEND(g[src], ag[dst], al);
- ab[dst] = CD_ALPHA_BLEND(b[src], ab[dst], al);
- }
- }
-
- canvas->cxPutImageRectRGB(canvas->ctxcanvas, w, h, ar, ag, ab, x, y, w, h, 0, 0, 0, 0);
-
- free(ar);
-
- free(fx);
- free(fy);
-}
diff --git a/cd/src/sim/sim_primitives.c b/cd/src/sim/sim_primitives.c
index dc991f8..2040c66 100755
--- a/cd/src/sim/sim_primitives.c
+++ b/cd/src/sim/sim_primitives.c
@@ -11,96 +11,75 @@
#include "cd.h"
#include "cd_private.h"
-#include "sim.h"
-void cdlineSIM(cdCtxCanvas* ctxcanvas, int x1, int y1, int x2, int y2)
+
+void cdSimLine(cdCtxCanvas* ctxcanvas, int x1, int y1, int x2, int y2)
{
cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
- int old_use_matrix = canvas->use_matrix;
-
- if (canvas->use_matrix && !canvas->invert_yaxis)
- {
- cdMatrixTransformPoint(canvas->matrix, x1, y1, &x1, &y1);
- cdMatrixTransformPoint(canvas->matrix, x2, y2, &x2, &y2);
- }
-
- /* must disable transformation here, because line simulation use cxPixel */
- canvas->use_matrix = 0;
-
- if(canvas->line_width > 1)
- simLineThick(canvas, x1, y1, x2, y2);
- else
- simLineThin(canvas, x1, y1, x2, y2);
+ cdPoint poly[2];
+ poly[0].x = x1; poly[0].y = y1;
+ poly[1].x = x2; poly[1].y = y2;
+ cdCanvasPoly(canvas, CD_OPEN_LINES, poly, 2);
+}
- canvas->use_matrix = old_use_matrix;
+void cdfSimLine(cdCtxCanvas* ctxcanvas, double x1, double y1, double x2, double y2)
+{
+ cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
+ cdfPoint poly[2];
+ poly[0].x = x1; poly[0].y = y1;
+ poly[1].x = x2; poly[1].y = y2;
+ canvas->cxFPoly(canvas->ctxcanvas, CD_OPEN_LINES, poly, 2);
}
-void cdrectSIM(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+void cdSimRect(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax)
{
cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
- cdPoint poly[5]; /* leave room of one more point */
+ cdPoint poly[5]; /* leave room for one more point */
poly[0].x = xmin; poly[0].y = ymin;
poly[1].x = xmin; poly[1].y = ymax;
poly[2].x = xmax; poly[2].y = ymax;
poly[3].x = xmax; poly[3].y = ymin;
- canvas->cxPoly(canvas->ctxcanvas, CD_CLOSED_LINES, poly, 4);
+ cdCanvasPoly(canvas, CD_CLOSED_LINES, poly, 4);
}
-void cdboxSIM(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax)
+void cdfSimRect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
{
+ /* can be used only by drivers that implement cxFPoly */
cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
-
- if (canvas->use_matrix)
- {
- cdPoint poly[5]; /* leave room of one more point */
- poly[0].x = xmin; poly[0].y = ymin;
- poly[1].x = xmin; poly[1].y = ymax;
- poly[2].x = xmax; poly[2].y = ymax;
- poly[3].x = xmax; poly[3].y = ymin;
- canvas->cxPoly(canvas->ctxcanvas, CD_FILL, poly, 4);
- }
- else
- {
- cdSimulation* simulation = canvas->simulation;
- int y;
-
- /* must set line attributes here, because fill simulation use cxLine and cxPixel */
- int old_line_style = cdCanvasLineStyle(canvas, CD_CONTINUOUS);
- int old_line_width = cdCanvasLineWidth(canvas, 1);
-
- for(y=ymin;y<=ymax;y++)
- simFillHorizLine(simulation, xmin, y, xmax);
-
- cdCanvasLineStyle(canvas, old_line_style);
- cdCanvasLineWidth(canvas, old_line_width);
- }
+ cdfPoint poly[5]; /* leave room for one more point */
+ poly[0].x = xmin; poly[0].y = ymin;
+ poly[1].x = xmin; poly[1].y = ymax;
+ poly[2].x = xmax; poly[2].y = ymax;
+ poly[3].x = xmax; poly[3].y = ymin;
+ canvas->cxFPoly(canvas->ctxcanvas, CD_CLOSED_LINES, poly, 4);
}
-void cdfSimBox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
+void cdSimBox(cdCtxCanvas* ctxcanvas, int xmin, int xmax, int ymin, int ymax)
{
cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
- cdfPoint poly[5]; /* leave room of one more point */
+ cdPoint poly[5]; /* leave room for one more point */
poly[0].x = xmin; poly[0].y = ymin;
poly[1].x = xmin; poly[1].y = ymax;
poly[2].x = xmax; poly[2].y = ymax;
poly[3].x = xmax; poly[3].y = ymin;
- canvas->cxFPoly(canvas->ctxcanvas, CD_FILL, poly, 4);
+ cdCanvasPoly(canvas, CD_FILL, poly, 4);
}
-void cdfSimRect(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
+void cdfSimBox(cdCtxCanvas *ctxcanvas, double xmin, double xmax, double ymin, double ymax)
{
+ /* can be used only by drivers that implement cxFPoly */
cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
- cdfPoint poly[5]; /* leave room of one more point */
+ cdfPoint poly[5]; /* leave room for one more point */
poly[0].x = xmin; poly[0].y = ymin;
poly[1].x = xmin; poly[1].y = ymax;
poly[2].x = xmax; poly[2].y = ymax;
poly[3].x = xmax; poly[3].y = ymin;
- canvas->cxFPoly(canvas->ctxcanvas, CD_CLOSED_LINES, poly, 4);
+ canvas->cxFPoly(canvas->ctxcanvas, CD_FILL, poly, 4);
}
-int simCalcEllipseNumSegments(cdCanvas* canvas, int xc, int yc, int width, int height)
+static int sCalcEllipseNumSegments(cdCanvas* canvas, int xc, int yc, int width, int height, double angle1, double angle2)
{
- int n, dx, dy, hd;
+ int K, dx, dy, hd;
int w2 = width/2;
int h2 = height/2;
int x1 = xc-w2,
@@ -114,6 +93,8 @@ int simCalcEllipseNumSegments(cdCanvas* canvas, int xc, int yc, int width, int h
cdMatrixTransformPoint(canvas->matrix, x2, y2, &x2, &y2);
}
+ /* first calculate the number of segments of equivalent poligonal for a full ellipse */
+
dx = (x1-x2);
dy = (y1-y2);
hd = (int)(sqrt(dx*dx + dy*dy)/2);
@@ -125,51 +106,61 @@ int simCalcEllipseNumSegments(cdCanvas* canvas, int xc, int yc, int width, int h
The number of segments will be 360 / min_angle.
*/
- n = (int)((360.0*CD_DEG2RAD) / acos((double)hd / (hd + 1.0)) + 0.5); /* round up */
+ K = (int)((360.0*CD_DEG2RAD) / acos((double)hd / (hd + 1.0)) + 0.5); /* round up */
/* multiple of 4 */
- n = ((n + 3)/4)*4;
+ K = ((K + 3)/4)*4;
/* minimum number is 4 */
- if (n < 4) n = 4;
+ if (K < 4) K = 4;
+
- return n;
+ /* finally, calculate the number of segments for the arc */
+ K = cdRound((fabs(angle2-angle1)*K)/(360*CD_DEG2RAD));
+ if (K < 1) K = 1;
+
+ return K;
}
-void cdarcSIM(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int height, double angle1, double angle2)
+static void sFixAngles(cdCanvas* canvas, double *a1, double *a2)
{
- cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
- double c, s, sx, sy, x, y, prev_x, prev_y;
- double da;
- int i, yc2 = 2*yc, p = 0,
- last_xi_a = -65535,
- last_yi_a = -65535,
- last_xi_b = -65535,
- last_yi_b = -65535;
- cdPoint* poly = NULL;
+ /* computation in PolyAddArc is done as if the angles are counterclockwise,
+ and yaxis is NOT inverted. */
- /* number of segments of equivalent poligonal for a full ellipse */
- int n = simCalcEllipseNumSegments(canvas, xc, yc, width, height);
-
- /* Use special floating point anti-alias line draw when
- line_width==1, and NOT using cdlineSIM. */
- if (canvas->line_width > 1 || canvas->cxLine != cdlineSIM)
+ if (canvas->invert_yaxis)
{
- poly = (cdPoint*)malloc(sizeof(cdPoint)*(n+1)); /* n+1 points */
- if (!poly) return;
+ /* change orientation */
+ *a1 *= -1;
+ *a2 *= -1;
+
+ /* no need to swap, because we will use (angle2-angle1) */
}
+ /* convert to radians */
+ *a1 *= CD_DEG2RAD;
+ *a2 *= CD_DEG2RAD;
+}
+
+static cdPoint* sPolyAddArc(cdCanvas* canvas, cdPoint* poly, int *n, int xc, int yc, int width, int height, double angle1, double angle2, cdPoint* current)
+{
+ double c, s, sx, sy, x, y, prev_x, prev_y;
+ double da;
+ int i, K, k, p, new_n;
+ cdPoint* old_poly = poly;
+
+ sFixAngles(canvas, &angle1, &angle2);
+
/* number of segments for the arc */
- n = cdRound((fabs(angle2-angle1)*n)/360);
- if (n < 1) n = 1;
+ K = sCalcEllipseNumSegments(canvas, xc, yc, width, height, angle1, angle2);
- /* converts degrees into radians */
- angle1 *= CD_DEG2RAD;
- angle2 *= CD_DEG2RAD;
+ new_n = *n + K+1; /* add room for K+1 samples */
+ poly = (cdPoint*)realloc(poly, sizeof(cdPoint)*(new_n+2)); /* add room also for points at start and end */
+ if (!poly) {free(old_poly); return NULL;}
+ i = *n;
/* generates arc points at origin with axis x and y */
- da = (angle2-angle1)/n;
+ da = (angle2-angle1)/K;
c = cos(da);
s = sin(da);
sx = -(width*s)/height;
@@ -179,100 +170,56 @@ void cdarcSIM(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int height, dou
y = (height/2.0f)*sin(angle1);
prev_x = x;
prev_y = y;
- if (poly)
- {
- poly[0].x = _cdRound(x)+xc;
- poly[0].y = _cdRound(y)+yc;
-
- if (canvas->invert_yaxis) /* must invert because of the angle orientation */
- poly[0].y = yc2 - poly[0].y;
- p = 1;
+ if (current)
+ {
+ poly[i] = *current;
+ i++;
+ new_n++; /* no need to reallocate */
}
- else
- simLineStyleNoReset = 1;
- for (i = 1; i < n+1; i++) /* n+1 points */
+ poly[i].x = _cdRound(x)+xc;
+ poly[i].y = _cdRound(y)+yc;
+
+ p = i+1;
+ for (k = 1; k < K+1; k++)
{
x = c*prev_x + sx*prev_y;
y = sy*prev_x + c*prev_y;
- if (poly)
- {
- poly[p].x = _cdRound(x)+xc;
- poly[p].y = _cdRound(y)+yc;
-
- if (canvas->invert_yaxis) /* must invert because of the angle orientation */
- poly[p].y = yc2 - poly[p].y;
-
- if (poly[p-1].x != poly[p].x || poly[p-1].y != poly[p].y)
- p++;
- }
- else
- {
- int old_use_matrix = canvas->use_matrix;
- double x1 = prev_x+xc,
- y1 = prev_y+yc,
- x2 = x+xc,
- y2 = y+yc;
-
- if (canvas->use_matrix && !canvas->invert_yaxis)
- {
- cdfMatrixTransformPoint(canvas->matrix, x1, y1, &x1, &y1);
- cdfMatrixTransformPoint(canvas->matrix, x2, y2, &x2, &y2);
- }
-
- /* must disable transformation here, because line simulation use cxPixel */
- canvas->use_matrix = 0;
-
- if (canvas->invert_yaxis) /* must invert because of the angle orientation */
- {
- y1 = yc2 - y1;
- y2 = yc2 - y2;
- }
-
- simfLineThin(canvas, x1, y1, x2, y2, &last_xi_a, &last_yi_a, &last_xi_b, &last_yi_b);
+ poly[p].x = _cdRound(x)+xc;
+ poly[p].y = _cdRound(y)+yc;
- canvas->use_matrix = old_use_matrix;
- }
+ if (poly[p-1].x != poly[p].x ||
+ poly[p-1].y != poly[p].y)
+ p++;
prev_x = x;
prev_y = y;
}
- if (poly)
- {
- canvas->cxPoly(canvas->ctxcanvas, CD_OPEN_LINES, poly, p);
- free(poly);
- }
- else
- simLineStyleNoReset = 0;
+ *n = new_n;
+ return poly;
}
-void cdfSimArc(cdCtxCanvas *ctxcanvas, double xc, double yc, double width, double height, double angle1, double angle2)
+static cdfPoint* sfPolyAddArc(cdCanvas* canvas, cdfPoint* poly, int *n, double xc, double yc, double width, double height, double angle1, double angle2, cdfPoint* current)
{
- cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
double c, s, sx, sy, x, y, prev_x, prev_y, da;
- int i, p;
- cdfPoint* poly = NULL;
-
- /* number of segments of equivalent poligonal for a full ellipse */
- int n = simCalcEllipseNumSegments(canvas, (int)xc, (int)yc, (int)width, (int)height);
+ int i, k, K, p, new_n;
+ cdfPoint* old_poly = poly;
- poly = (cdfPoint*)malloc(sizeof(cdfPoint)*(n+1)); /* n+1 points */
- if (!poly) return;
+ sFixAngles(canvas, &angle1, &angle2);
/* number of segments for the arc */
- n = cdRound((fabs(angle2-angle1)*n)/360);
- if (n < 1) n = 1;
+ K = sCalcEllipseNumSegments(canvas, (int)xc, (int)yc, (int)width, (int)height, angle1, angle2);
- /* converts degrees into radians */
- angle1 *= CD_DEG2RAD;
- angle2 *= CD_DEG2RAD;
+ new_n = *n + K+1; /* add room for K+1 samples */
+ poly = (cdfPoint*)realloc(poly, sizeof(cdfPoint)*(new_n+2)); /* add room also for points at start and end */
+ if (!poly) {free(old_poly); return NULL;}
+ i = *n;
- /* generates arc points at origin with axis x and y */
-
- da = (angle2-angle1)/n;
+ /* generates arc points at origin with axis x and y */
+ da = (angle2-angle1)/K;
c = cos(da);
s = sin(da);
sx = -(width*s)/height;
@@ -282,12 +229,19 @@ void cdfSimArc(cdCtxCanvas *ctxcanvas, double xc, double yc, double width, doubl
y = (height/2.0f)*sin(angle1);
prev_x = x;
prev_y = y;
- poly[0].x = x+xc;
- poly[0].y = y+yc;
- p = 1;
+ if (current)
+ {
+ poly[i] = *current;
+ i++;
+ new_n++; /* no need to reallocate */
+ }
- for (i = 1; i < n+1; i++) /* n+1 points */
+ poly[i].x = x+xc;
+ poly[i].y = y+yc;
+
+ p = i+1;
+ for (k = 1; k < K+1; k++) /* K+1 points */
{
x = c*prev_x + sx*prev_y;
y = sy*prev_x + c*prev_y;
@@ -303,221 +257,1249 @@ void cdfSimArc(cdCtxCanvas *ctxcanvas, double xc, double yc, double width, doubl
prev_y = y;
}
- canvas->cxFPoly(canvas->ctxcanvas, CD_OPEN_LINES, poly, p);
- free(poly);
+ *n = new_n;
+ return poly;
}
-void cdfSimElipse(cdCtxCanvas* ctxcanvas, double xc, double yc, double width, double height, double angle1, double angle2, int sector)
+void cdSimArc(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int height, double angle1, double angle2)
{
cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
- double c, s, sx, sy, x, y, prev_x, prev_y, da;
- int i, p;
- cdfPoint* poly;
+ int n = 0;
+ cdPoint* poly = NULL;
- /* number of segments of equivalent poligonal for a full ellipse */
- int n = simCalcEllipseNumSegments(canvas, (int)xc, (int)yc, (int)width, (int)height);
+ if (canvas->line_width == 1 && canvas->cxFPoly)
+ {
+ cdfSimArc(ctxcanvas, (double)xc, (double)yc, (double)width, (double)height, angle1, angle2);
+ return;
+ }
- /* number of segments for the arc */
- n = cdRound(((angle2-angle1)*n)/360);
- if (n < 1) n = 1;
+ poly = sPolyAddArc(canvas, poly, &n, xc, yc, width, height, angle1, angle2, NULL);
- poly = (cdfPoint*)malloc(sizeof(cdfPoint)*(n+2+1)); /* n+1 points +1 center */
+ if (poly)
+ {
+ cdCanvasPoly(canvas, CD_OPEN_LINES, poly, n);
+ free(poly);
+ }
+}
- /* converts degrees into radians */
- angle1 *= CD_DEG2RAD;
- angle2 *= CD_DEG2RAD;
+void cdfSimArc(cdCtxCanvas *ctxcanvas, double xc, double yc, double width, double height, double angle1, double angle2)
+{
+ /* can be used only by drivers that implement cxFPoly */
+ cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
+ int n = 0;
+ cdfPoint* poly = NULL;
- /* generates arc points at origin with axis x and y */
+ poly = sfPolyAddArc(canvas, poly, &n, xc, yc, width, height, angle1, angle2, NULL);
- da = (angle2-angle1)/n;
- c = cos(da);
- s = sin(da);
- sx = -(width*s)/height;
- sy = (height*s)/width;
+ if (poly)
+ {
+ canvas->cxFPoly(canvas->ctxcanvas, CD_OPEN_LINES, poly, n);
+ free(poly);
+ }
+}
- x = xc + (width/2.0)*cos(angle1);
- y = yc + (height/2.0)*sin(angle1);
- prev_x = x;
- prev_y = y;
+static void sElipse(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int height, double angle1, double angle2, int sector)
+{
+ cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
+ int n = 0;
+ cdPoint* poly = NULL;
- poly[0].x = x;
- poly[0].y = y;
- p = 1;
+ poly = sPolyAddArc(canvas, poly, &n, xc, yc, width, height, angle1, angle2, NULL);
+ if (!poly)
+ return;
- for (i = 1; i < n+1; i++) /* n+1 points */
+ if (poly[n-1].x != poly[0].x ||
+ poly[n-1].y != poly[0].y)
{
- x = xc + c*(prev_x-xc) + sx*(prev_y-yc);
- y = yc + sy*(prev_x-xc) + c*(prev_y-yc);
-
- poly[p].x = x;
- poly[p].y = y;
+ n++; /* no need to reallocate */
- if (poly[p-1].x != poly[p].x || poly[p-1].y != poly[p].y)
- p++;
+ if (sector) /* cdSector */
+ {
+ /* add center */
+ poly[n-1].x = xc;
+ poly[n-1].y = yc;
+ }
+ else /* cdChord */
+ {
+ /* add initial point */
+ poly[n-1].x = poly[0].x;
+ poly[n-1].y = poly[0].y;
+ }
+ }
- prev_x = x;
- prev_y = y;
+ if (poly)
+ {
+ cdCanvasPoly(canvas, CD_FILL, poly, n);
+ free(poly);
}
+}
- if (poly[p-1].x != poly[0].x || poly[p-1].y != poly[0].y)
+static void sfElipse(cdCtxCanvas* ctxcanvas, double xc, double yc, double width, double height, double angle1, double angle2, int sector)
+{
+ /* can be used only by drivers that implement cxFPoly */
+ cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
+ int n = 0;
+ cdfPoint* poly = NULL;
+
+ poly = sfPolyAddArc(canvas, poly, &n, xc, yc, width, height, angle1, angle2, NULL);
+
+ if (poly[n-1].x != poly[0].x ||
+ poly[n-1].y != poly[0].y)
{
+ n++; /* no need to reallocate */
+
if (sector) /* cdSector */
{
/* add center */
- poly[p].x = xc;
- poly[p].y = yc;
+ poly[n-1].x = xc;
+ poly[n-1].y = yc;
}
else /* cdChord */
{
/* add initial point */
- poly[p].x = poly[0].x;
- poly[p].y = poly[0].y;
+ poly[n-1].x = poly[0].x;
+ poly[n-1].y = poly[0].y;
}
- p++;
}
- canvas->cxFPoly(canvas->ctxcanvas, CD_FILL, poly, p);
- free(poly);
+ if (poly)
+ {
+ canvas->cxFPoly(canvas->ctxcanvas, CD_FILL, poly, n);
+ free(poly);
+ }
}
-static void cdSimElipse(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int height, double angle1, double angle2, int sector)
+void cdSimSector(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int height, double angle1, double angle2)
{
- cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
- float c, s, sx, sy, x, y, prev_x, prev_y;
- double da;
- int i, p, yc2 = 2*yc;
- cdPoint* poly;
+ sElipse(ctxcanvas, xc, yc, width, height, angle1, angle2, 1);
+}
- /* number of segments of equivalent poligonal for a full ellipse */
- int n = simCalcEllipseNumSegments(canvas, xc, yc, width, height);
+void cdSimChord(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int height, double angle1, double angle2)
+{
+ sElipse(ctxcanvas, xc, yc, width, height, angle1, angle2, 0);
+}
- /* number of segments for the arc */
- n = cdRound(((angle2-angle1)*n)/360);
- if (n < 1) n = 1;
+void cdfSimSector(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
+{
+ sfElipse(ctxcanvas, xc, yc, w, h, a1, a2, 1);
+}
- poly = (cdPoint*)malloc(sizeof(cdPoint)*(n+2+1)); /* n+1 points +1 center */
+void cdfSimChord(cdCtxCanvas *ctxcanvas, double xc, double yc, double w, double h, double a1, double a2)
+{
+ sfElipse(ctxcanvas, xc, yc, w, h, a1, a2, 0);
+}
- /* converts degrees into radians */
- angle1 *= CD_DEG2RAD;
- angle2 *= CD_DEG2RAD;
+/**************************************************************/
+/* Quick and Simple Bezier Curve Drawing --- Robert D. Miller */
+/* Graphics GEMS V */
+/**************************************************************/
- /* generates arc points at origin with axis x and y */
+/* Setup Bezier coefficient array once for each control polygon.
+ */
+static void sBezierForm(cdPoint start, const cdPoint* p, cdfPoint* c)
+{
+ int k;
+ static int choose[4] = {1, 3, 3, 1};
+ for (k = 0; k < 4; k++)
+ {
+ if (k == 0)
+ {
+ c[k].x = start.x * choose[k];
+ c[k].y = start.y * choose[k];
+ }
+ else
+ {
+ c[k].x = p[k-1].x * choose[k];
+ c[k].y = p[k-1].y * choose[k];
+ }
+ }
+}
- da = (angle2-angle1)/n;
- c = (float)cos(da);
- s = (float)sin(da);
- sx = -(width*s)/height;
- sy = (height*s)/width;
+static void sfBezierForm(cdfPoint start, const cdfPoint* p, cdfPoint* c)
+{
+ int k;
+ static int choose[4] = {1, 3, 3, 1};
+ for (k = 0; k < 4; k++)
+ {
+ if (k == 0)
+ {
+ c[k].x = start.x * choose[k];
+ c[k].y = start.y * choose[k];
+ }
+ else
+ {
+ c[k].x = p[k-1].x * choose[k];
+ c[k].y = p[k-1].y * choose[k];
+ }
+ }
+}
- x = xc + (width/2.0f)*(float)cos(angle1);
- y = yc + (height/2.0f)*(float)sin(angle1);
- prev_x = x;
- prev_y = y;
+/* Return Point pt(t), t <= 0 <= 1 from C.
+ * sBezierForm must be called once for any given control polygon.
+ */
+static void sBezierCurve(const cdfPoint* c, cdfPoint *pt, double t)
+{
+ int k;
+ double t1, tt, u;
+ cdfPoint b[4];
- poly[0].x = _cdRound(x);
- poly[0].y = _cdRound(y);
- if (canvas->invert_yaxis)
- poly[0].y = yc2 - poly[0].y;
- p = 1;
+ u = t;
- for (i = 1; i < n+1; i++) /* n+1 points */
+ b[0].x = c[0].x;
+ b[0].y = c[0].y;
+ for(k = 1; k < 4; k++)
{
- x = xc + c*(prev_x-xc) + sx*(prev_y-yc);
- y = yc + sy*(prev_x-xc) + c*(prev_y-yc);
+ b[k].x = c[k].x * u;
+ b[k].y = c[k].y * u;
+ u =u*t;
+ }
- poly[p].x = _cdRound(x);
- poly[p].y = _cdRound(y);
+ pt->x = b[3].x;
+ pt->y = b[3].y;
+ t1 = 1-t;
+ tt = t1;
+ for(k = 2; k >= 0; k--)
+ {
+ pt->x += b[k].x * tt;
+ pt->y += b[k].y * tt;
+ tt =tt*t1;
+ }
+}
- if (canvas->invert_yaxis)
- poly[p].y = yc2 - poly[p].y;
+static int sBezierNumSegments(cdCanvas* canvas, cdPoint start, const cdPoint* p)
+{
+ int i, K, dx, dy, d,
+ xmax = start.x,
+ ymax = start.y,
+ xmin = start.x,
+ ymin = start.y;
- if (poly[p-1].x != poly[p].x || poly[p-1].y != poly[p].y)
- p++;
+ for (i = 1; i < 4; i++)
+ {
+ if (p[i].x > xmax)
+ xmax = p[i].x;
+ if (p[i].y > ymax)
+ ymax = p[i].y;
+ if (p[i].x < xmin)
+ xmin = p[i].x;
+ if (p[i].y < ymin)
+ ymin = p[i].y;
+ }
- prev_x = x;
- prev_y = y;
+ if (canvas->use_matrix)
+ {
+ cdMatrixTransformPoint(canvas->matrix, xmin, ymin, &xmin, &ymin);
+ cdMatrixTransformPoint(canvas->matrix, xmax, ymax, &xmax, &ymax);
}
- if (poly[p-1].x != poly[0].x || poly[p-1].y != poly[0].y)
+ /* diagonal of the bouding box */
+ dx = (xmax-xmin);
+ dy = (ymax-ymin);
+ d = (int)(sqrt(dx*dx + dy*dy));
+ K = d / 8;
+ if (K < 8) K = 8;
+ return K;
+}
+
+static int sfBezierNumSegments(cdCanvas* canvas, cdfPoint start, const cdfPoint* p)
+{
+ int i, K, d;
+ double dx, dy,
+ xmax = start.x,
+ ymax = start.y,
+ xmin = start.x,
+ ymin = start.y;
+
+ for (i = 1; i < 4; i++)
{
- if (sector) /* cdSector */
+ if (p[i].x > xmax)
+ xmax = p[i].x;
+ if (p[i].y > ymax)
+ ymax = p[i].y;
+ if (p[i].x < xmin)
+ xmin = p[i].x;
+ if (p[i].y < ymin)
+ ymin = p[i].y;
+ }
+
+ if (canvas->use_matrix)
+ {
+ cdfMatrixTransformPoint(canvas->matrix, xmin, ymin, &xmin, &ymin);
+ cdfMatrixTransformPoint(canvas->matrix, xmax, ymax, &xmax, &ymax);
+ }
+
+ /* diagonal of the bouding box */
+ dx = (xmax-xmin);
+ dy = (ymax-ymin);
+ d = (int)(sqrt(dx*dx + dy*dy));
+ K = d / 8;
+ if (K < 8) K = 8;
+ return K;
+}
+
+static cdPoint* sPolyAddBezier(cdCanvas* canvas, cdPoint* poly, int *n, cdPoint start, const cdPoint* points)
+{
+ int k, K, new_n, i;
+ cdfPoint pt;
+ cdfPoint bezier_control[4];
+ cdPoint* old_poly = poly;
+
+ sBezierForm(start, points, bezier_control);
+ K = sBezierNumSegments(canvas, start, points);
+
+ new_n = *n + K+1; /* add room for K+1 samples */
+ poly = realloc(poly, sizeof(cdPoint)*new_n);
+ if (!poly) {free(old_poly); return NULL;}
+ i = *n;
+
+ /* first segment */
+ sBezierCurve(bezier_control, &pt, 0);
+
+ poly[i].x = _cdRound(pt.x);
+ poly[i].y = _cdRound(pt.y);
+
+ for(k = 1; k < K+1; k++)
+ {
+ sBezierCurve(bezier_control, &pt, (double)k/(double)K);
+
+ poly[i+k].x = _cdRound(pt.x);
+ poly[i+k].y = _cdRound(pt.y);
+ }
+
+ *n = new_n;
+ return poly;
+}
+
+static cdfPoint* sPolyFAddBezier(cdCanvas* canvas, cdfPoint* poly, int *n, cdfPoint start, const cdPoint* points)
+{
+ int k, K, new_n, i;
+ cdfPoint pt;
+ cdfPoint bezier_control[4], bezier[3];
+ cdfPoint* old_poly = poly;
+
+ bezier[0].x = points[0].x; bezier[1].x = points[1].x; bezier[2].x = points[2].x;
+ bezier[0].y = points[0].y; bezier[1].y = points[1].y; bezier[2].y = points[2].y;
+
+ sfBezierForm(start, bezier, bezier_control);
+ K = sfBezierNumSegments(canvas, start, bezier);
+
+ new_n = *n + K+1; /* add room for K+1 samples */
+ poly = realloc(poly, sizeof(cdfPoint)*new_n);
+ if (!poly) {free(old_poly); return NULL;}
+ i = *n;
+
+ /* first segment */
+ sBezierCurve(bezier_control, &pt, 0);
+
+ poly[i] = pt;
+
+ for(k = 1; k < K+1; k++)
+ {
+ sBezierCurve(bezier_control, &pt, (double)k/(double)K);
+ poly[i+k] = pt;
+ }
+
+ *n = new_n;
+ return poly;
+}
+
+static cdfPoint* sfPolyAddBezier(cdCanvas* canvas, cdfPoint* poly, int *n, cdfPoint start, const cdfPoint* points)
+{
+ int k, K, new_n, i;
+ cdfPoint pt;
+ cdfPoint bezier_control[4];
+ cdfPoint* old_poly = poly;
+
+ sfBezierForm(start, points, bezier_control);
+ K = sfBezierNumSegments(canvas, start, points);
+
+ new_n = *n + K+1; /* add room for K+1 samples */
+ poly = realloc(poly, sizeof(cdfPoint)*new_n);
+ if (!poly) {free(old_poly); return NULL;}
+ i = *n;
+
+ /* first segment */
+ sBezierCurve(bezier_control, &pt, 0);
+
+ poly[i] = pt;
+
+ for(k = 1; k < K+1; k++)
+ {
+ sBezierCurve(bezier_control, &pt, (double)k/(double)K);
+ poly[i+k] = pt;
+ }
+
+ *n = new_n;
+ return poly;
+}
+
+static void sPolyFBezier(cdCanvas* canvas, const cdPoint* points, int n)
+{
+ int i = 0, poly_n = 0;
+ cdfPoint* fpoly = NULL, start;
+
+ start.x = points[0].x;
+ start.y = points[0].y;
+
+ n--; /* first n is 4 */
+ while (n >= 3)
+ {
+ fpoly = sPolyFAddBezier(canvas, fpoly, &poly_n, start, points+i+1);
+ start = fpoly[poly_n-1];
+ n -= 3; i += 3;
+ }
+
+ if (fpoly)
+ {
+ canvas->cxFPoly(canvas->ctxcanvas, CD_OPEN_LINES, fpoly, poly_n);
+ free(fpoly);
+ }
+}
+
+void cdSimPolyBezier(cdCanvas* canvas, const cdPoint* points, int n)
+{
+ int i = 0, poly_n = 0;
+ cdPoint* poly = NULL;
+
+ if (canvas->line_width == 1 && canvas->cxFPoly)
+ {
+ sPolyFBezier(canvas, points, n);
+ return;
+ }
+
+ n--; /* first n is 4 */
+ while (n >= 3)
+ {
+ poly = sPolyAddBezier(canvas, poly, &poly_n, points[i], points+i+1);
+ if (!poly) return;
+ n -= 3; i += 3;
+ }
+
+ if (poly)
+ {
+ cdCanvasPoly(canvas, CD_OPEN_LINES, poly, poly_n);
+ free(poly);
+ }
+}
+
+void cdfSimPolyBezier(cdCanvas* canvas, const cdfPoint* points, int n)
+{
+ /* can be used only by drivers that implement cxFPoly */
+ int i = 0, poly_n = 0;
+ cdfPoint* poly = NULL;
+
+ n--; /* first n is 4 */
+ while (n >= 3)
+ {
+ poly = sfPolyAddBezier(canvas, poly, &poly_n, points[i], points+i+1);
+ n -= 3; i += 3;
+ }
+
+ if (poly)
+ {
+ canvas->cxFPoly(canvas->ctxcanvas, CD_OPEN_LINES, poly, poly_n);
+ free(poly);
+ }
+}
+
+static cdPoint* sPolyAddLine(cdPoint* poly, int *n, cdPoint p1, cdPoint p2)
+{
+ int new_n, i;
+ cdPoint* old_poly = poly;
+
+ new_n = *n + 2;
+ poly = realloc(poly, sizeof(cdPoint)*new_n);
+ if (!poly) {free(old_poly); return NULL;}
+ i = *n;
+
+ poly[i] = p1;
+ poly[i+1] = p2;
+
+ *n = new_n;
+ return poly;
+}
+
+static cdfPoint* sfPolyAddLine(cdfPoint* poly, int *n, cdfPoint p1, cdfPoint p2)
+{
+ int new_n, i;
+ cdfPoint* old_poly = poly;
+
+ new_n = *n + 2;
+ poly = realloc(poly, sizeof(cdfPoint)*new_n);
+ if (!poly) {free(old_poly); return NULL;}
+ i = *n;
+
+ poly[i] = p1;
+ poly[i+1] = p2;
+
+ *n = new_n;
+ return poly;
+}
+
+void cdfSimPolyPath(cdCanvas* canvas, const cdfPoint* poly, int n)
+{
+ int p, i, current_set = 0, path_poly_n;
+ cdfPoint current;
+ cdfPoint* path_poly, *old_path_poly;
+
+ current.x = 0;
+ current.y = 0;
+ current_set = 0;
+
+ /* starts a new path */
+ path_poly = NULL;
+ path_poly_n = 0;
+
+ i = 0;
+ for (p=0; p<canvas->path_n; p++)
+ {
+ switch(canvas->path[p])
{
- /* add center */
- poly[p].x = xc;
- poly[p].y = yc;
+ case CD_PATH_NEW:
+ if (path_poly)
+ free(path_poly);
+ path_poly = NULL;
+ path_poly_n = 0;
+ current_set = 0;
+ break;
+ case CD_PATH_MOVETO:
+ if (i+1 > n) break;
+ current = poly[i];
+ current_set = 1;
+ i++;
+ break;
+ case CD_PATH_LINETO:
+ if (i+1 > n) break;
+ path_poly = sfPolyAddLine(path_poly, &path_poly_n, current, poly[i]);
+ current = poly[i];
+ current_set = 1;
+ i++;
+ break;
+ case CD_PATH_ARC:
+ {
+ double xc, yc, w, h;
+ double a1, a2;
+
+ if (i+3 > n) break;
+
+ if (!cdfCanvasGetArcPath(canvas, poly+i, &xc, &yc, &w, &h, &a1, &a2))
+ return;
+
+ if (current_set)
+ path_poly = sfPolyAddArc(canvas, path_poly, &path_poly_n, xc, yc, w, h, a1, a2, &current);
+ else
+ path_poly = sfPolyAddArc(canvas, path_poly, &path_poly_n, xc, yc, w, h, a1, a2, NULL);
+
+ current = path_poly[path_poly_n-1];
+ current_set = 1;
+
+ i += 3;
+ }
+ break;
+ case CD_PATH_CURVETO:
+ if (i+3 > n) break;
+ if (!current_set)
+ {
+ current.x = poly[i].x;
+ current.y = poly[i].y;
+ }
+ path_poly = sfPolyAddBezier(canvas, path_poly, &path_poly_n, current, poly+i);
+ current = path_poly[path_poly_n-1];
+ current_set = 1;
+ i += 3;
+ break;
+ case CD_PATH_CLOSE:
+ if (path_poly[path_poly_n-1].x != path_poly[0].x ||
+ path_poly[path_poly_n-1].y != path_poly[0].y)
+ {
+ path_poly_n++;
+ old_path_poly = path_poly;
+ path_poly = (cdfPoint*)realloc(path_poly, sizeof(cdfPoint)*path_poly_n);
+ if (!path_poly) {free(old_path_poly); return;}
+
+ /* add initial point */
+ path_poly[path_poly_n-1].x = path_poly[0].x;
+ path_poly[path_poly_n-1].y = path_poly[0].y;
+ }
+ break;
+ case CD_PATH_FILL:
+ if (poly)
+ canvas->cxFPoly(canvas->ctxcanvas, CD_FILL, path_poly, path_poly_n);
+ break;
+ case CD_PATH_STROKE:
+ if (poly)
+ canvas->cxFPoly(canvas->ctxcanvas, CD_OPEN_LINES, path_poly, path_poly_n);
+ break;
+ case CD_PATH_FILLSTROKE:
+ if (poly)
+ {
+ canvas->cxFPoly(canvas->ctxcanvas, CD_FILL, path_poly, path_poly_n);
+ canvas->cxFPoly(canvas->ctxcanvas, CD_OPEN_LINES, path_poly, path_poly_n);
+ }
+ break;
+ case CD_PATH_CLIP:
+ if (poly)
+ canvas->cxFPoly(canvas->ctxcanvas, CD_CLIP, path_poly, path_poly_n);
+ break;
}
- else /* cdChord */
+ }
+
+ if (path_poly)
+ free(path_poly);
+}
+
+static void sSimPolyFPath(cdCanvas* canvas, const cdPoint* poly, int n)
+{
+ int p, i, current_set = 0, path_poly_n;
+ cdfPoint current, pt;
+ cdfPoint* path_poly, *old_path_poly;
+
+ current.x = 0;
+ current.y = 0;
+ current_set = 0;
+
+ /* starts a new path */
+ path_poly = NULL;
+ path_poly_n = 0;
+
+ i = 0;
+ for (p=0; p<canvas->path_n; p++)
+ {
+ switch(canvas->path[p])
{
- /* add initial point */
- poly[p].x = poly[0].x;
- poly[p].y = poly[0].y;
+ case CD_PATH_NEW:
+ if (path_poly)
+ free(path_poly);
+ path_poly = NULL;
+ path_poly_n = 0;
+ current_set = 0;
+ break;
+ case CD_PATH_MOVETO:
+ if (i+1 > n) break;
+ current.x = poly[i].x;
+ current.y = poly[i].y;
+ current_set = 1;
+ i++;
+ break;
+ case CD_PATH_LINETO:
+ if (i+1 > n) break;
+ pt.x = poly[i].x;
+ pt.y = poly[i].y;
+ path_poly = sfPolyAddLine(path_poly, &path_poly_n, current, pt);
+ current.x = poly[i].x;
+ current.y = poly[i].y;
+ current_set = 1;
+ i++;
+ break;
+ case CD_PATH_ARC:
+ {
+ double xc, yc, w, h;
+ double a1, a2;
+
+ if (i+3 > n) break;
+
+ if (!cdCanvasGetArcPathF(canvas, poly+i, &xc, &yc, &w, &h, &a1, &a2))
+ return;
+
+ if (current_set)
+ path_poly = sfPolyAddArc(canvas, path_poly, &path_poly_n, xc, yc, w, h, a1, a2, &current);
+ else
+ path_poly = sfPolyAddArc(canvas, path_poly, &path_poly_n, xc, yc, w, h, a1, a2, NULL);
+
+ current = path_poly[path_poly_n-1];
+ current_set = 1;
+
+ i += 3;
+ }
+ break;
+ case CD_PATH_CURVETO:
+ if (i+3 > n) break;
+ if (!current_set)
+ {
+ current.x = poly[i].x;
+ current.y = poly[i].y;
+ }
+ path_poly = sPolyFAddBezier(canvas, path_poly, &path_poly_n, current, poly+i);
+ current = path_poly[path_poly_n-1];
+ current_set = 1;
+ i += 3;
+ break;
+ case CD_PATH_CLOSE:
+ if (path_poly[path_poly_n-1].x != path_poly[0].x ||
+ path_poly[path_poly_n-1].y != path_poly[0].y)
+ {
+ path_poly_n++;
+ old_path_poly = path_poly;
+ path_poly = (cdfPoint*)realloc(path_poly, sizeof(cdfPoint)*path_poly_n);
+ if (!path_poly) {free(old_path_poly); return;}
+
+ /* add initial point */
+ path_poly[path_poly_n-1].x = path_poly[0].x;
+ path_poly[path_poly_n-1].y = path_poly[0].y;
+ }
+ break;
+ case CD_PATH_FILL:
+ if (poly)
+ canvas->cxFPoly(canvas->ctxcanvas, CD_FILL, path_poly, path_poly_n);
+ break;
+ case CD_PATH_STROKE:
+ if (poly)
+ canvas->cxFPoly(canvas->ctxcanvas, CD_OPEN_LINES, path_poly, path_poly_n);
+ break;
+ case CD_PATH_FILLSTROKE:
+ if (poly)
+ {
+ canvas->cxFPoly(canvas->ctxcanvas, CD_FILL, path_poly, path_poly_n);
+ canvas->cxFPoly(canvas->ctxcanvas, CD_OPEN_LINES, path_poly, path_poly_n);
+ }
+ break;
+ case CD_PATH_CLIP:
+ if (poly)
+ canvas->cxFPoly(canvas->ctxcanvas, CD_CLIP, path_poly, path_poly_n);
+ break;
}
- p++;
}
- canvas->cxPoly(canvas->ctxcanvas, CD_FILL, poly, p);
-
- free(poly);
+ if (path_poly)
+ free(path_poly);
}
-void cdsectorSIM(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int height, double angle1, double angle2)
+void cdSimPolyPath(cdCanvas* canvas, const cdPoint* poly, int n)
{
- cdSimElipse(ctxcanvas, xc, yc, width, height, angle1, angle2, 1);
+ int p, i, current_set = 0, path_poly_n;
+ cdPoint current;
+ cdPoint* path_poly, *old_path_poly;
+
+ if (canvas->line_width == 1 && canvas->cxFPoly)
+ {
+ int has_curve = 0;
+ for (p=0; p<canvas->path_n; p++)
+ {
+ if (canvas->path[p] == CD_PATH_ARC ||
+ canvas->path[p] == CD_PATH_CURVETO)
+ has_curve = 1;
+ if (canvas->path[p] == CD_PATH_STROKE &&
+ has_curve == 1)
+ {
+ sSimPolyFPath(canvas, poly, n);
+ return;
+ }
+ }
+ }
+
+ current.x = 0;
+ current.y = 0;
+ current_set = 0;
+
+ /* starts a new path */
+ path_poly = NULL;
+ path_poly_n = 0;
+
+ i = 0;
+ for (p=0; p<canvas->path_n; p++)
+ {
+ switch(canvas->path[p])
+ {
+ case CD_PATH_NEW:
+ if (path_poly)
+ free(path_poly);
+ path_poly = NULL;
+ path_poly_n = 0;
+ current_set = 0;
+ break;
+ case CD_PATH_MOVETO:
+ if (i+1 > n) break;
+ current = poly[i];
+ current_set = 1;
+ i++;
+ break;
+ case CD_PATH_LINETO:
+ if (i+1 > n) break;
+ path_poly = sPolyAddLine(path_poly, &path_poly_n, current, poly[i]);
+ if (!path_poly) return;
+ current = poly[i];
+ current_set = 1;
+ i++;
+ break;
+ case CD_PATH_ARC:
+ {
+ int xc, yc, w, h;
+ double a1, a2;
+
+ if (i+3 > n) break;
+
+ if (!cdCanvasGetArcPath(canvas, poly+i, &xc, &yc, &w, &h, &a1, &a2))
+ return;
+
+ if (current_set)
+ path_poly = sPolyAddArc(canvas, path_poly, &path_poly_n, xc, yc, w, h, a1, a2, &current);
+ else
+ path_poly = sPolyAddArc(canvas, path_poly, &path_poly_n, xc, yc, w, h, a1, a2, NULL);
+ if (!path_poly) return;
+
+ current = path_poly[path_poly_n-1];
+ current_set = 1;
+
+ i += 3;
+ }
+ break;
+ case CD_PATH_CURVETO:
+ if (i+3 > n) break;
+ if (!current_set)
+ {
+ current.x = poly[i].x;
+ current.y = poly[i].y;
+ }
+ path_poly = sPolyAddBezier(canvas, path_poly, &path_poly_n, current, poly+i);
+ if (!path_poly) return;
+ current = path_poly[path_poly_n-1];
+ current_set = 1;
+ i += 3;
+ break;
+ case CD_PATH_CLOSE:
+ if (path_poly[path_poly_n-1].x != path_poly[0].x ||
+ path_poly[path_poly_n-1].y != path_poly[0].y)
+ {
+ path_poly_n++;
+ old_path_poly = path_poly;
+ path_poly = (cdPoint*)realloc(path_poly, sizeof(cdPoint)*path_poly_n);
+ if (!path_poly) {free(old_path_poly); return;}
+
+ /* add initial point */
+ path_poly[path_poly_n-1].x = path_poly[0].x;
+ path_poly[path_poly_n-1].y = path_poly[0].y;
+ }
+ break;
+ case CD_PATH_FILL:
+ if (poly)
+ cdCanvasPoly(canvas, CD_FILL, path_poly, path_poly_n);
+ break;
+ case CD_PATH_STROKE:
+ if (poly)
+ cdCanvasPoly(canvas, CD_OPEN_LINES, path_poly, path_poly_n);
+ break;
+ case CD_PATH_FILLSTROKE:
+ if (poly)
+ {
+ cdCanvasPoly(canvas, CD_FILL, path_poly, path_poly_n);
+ cdCanvasPoly(canvas, CD_OPEN_LINES, path_poly, path_poly_n);
+ }
+ break;
+ case CD_PATH_CLIP:
+ if (poly)
+ cdCanvasPoly(canvas, CD_CLIP, path_poly, path_poly_n);
+ break;
+ }
+ }
+
+ if (path_poly)
+ free(path_poly);
}
-void cdchordSIM(cdCtxCanvas* ctxcanvas, int xc, int yc, int width, int height, double angle1, double angle2)
+/************************************************************************/
+
+/* Simulation functions that depend on the simulation base driver. */
+static void cdSimPolyFill(cdCanvas* canvas, cdPoint* poly, int n);
+static void cdSimPolyLine(cdCanvas* canvas, const cdPoint* poly, int n);
+static void cdfSimPolyLine(cdCanvas* canvas, const cdfPoint* poly, int n);
+
+void cdSimPoly(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n)
{
- cdSimElipse(ctxcanvas, xc, yc, width, height, angle1, angle2, 0);
+ cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
+
+ switch(mode)
+ {
+ case CD_CLOSED_LINES:
+ poly[n] = poly[0]; /* can do that because poly is internal of the CD */
+ n++;
+ /* continue */
+ case CD_OPEN_LINES:
+ cdSimPolyLine(canvas, poly, n);
+ break;
+ case CD_BEZIER:
+ cdSimPolyBezier(canvas, poly, n);
+ break;
+ case CD_PATH:
+ cdSimPolyPath(canvas, poly, n);
+ break;
+ case CD_FILL:
+ cdSimPolyFill(canvas, poly, n);
+ break;
+ }
}
-void cdpolySIM(cdCtxCanvas* ctxcanvas, int mode, cdPoint* poly, int n)
+void cdfSimPoly(cdCtxCanvas* ctxcanvas, int mode, cdfPoint* fpoly, int n)
{
cdCanvas* canvas = ((cdCtxCanvasBase*)ctxcanvas)->canvas;
- int i, reset = 1;
switch(mode)
{
case CD_CLOSED_LINES:
- poly[n] = poly[0];
+ fpoly[n] = fpoly[0];
n++;
/* continue */
case CD_OPEN_LINES:
- if (simLineStyleNoReset) /* Bezier simulation use several poly */
- {
- reset = 0;
- simLineStyleNoReset = 1;
- }
- for (i = 0; i< n - 1; i++)
- canvas->cxLine(canvas->ctxcanvas, poly[i].x, poly[i].y, poly[i+1].x, poly[i+1].y);
- if (reset) simLineStyleNoReset = 0;
+ cdfSimPolyLine(canvas, fpoly, n);
break;
case CD_BEZIER:
- simLineStyleNoReset = 1;
- cdSimPolyBezier(canvas, poly, n);
- simLineStyleNoReset = 0;
+ cdfSimPolyBezier(canvas, fpoly, n);
+ break;
+ case CD_PATH:
+ cdfSimPolyPath(canvas, fpoly, n);
break;
+ case CD_CLIP:
case CD_FILL:
{
- /* must set line attributes here, because fill simulation use cxLine */
- int oldwidth = cdCanvasLineWidth(canvas, 1);
- int oldstyle = cdCanvasLineStyle(canvas, CD_CONTINUOUS);
- int old_use_matrix = canvas->use_matrix;
+ cdPoint* poly = malloc(sizeof(cdPoint)*n);
+ int i;
- if (canvas->use_matrix && !canvas->invert_yaxis)
+ for (i = 0; i<n; i++)
{
- for(i = 0; i < n; i++)
- cdMatrixTransformPoint(canvas->matrix, poly[i].x, poly[i].y, &poly[i].x, &poly[i].y);
+ poly[i].x = _cdRound(fpoly[i].x);
+ poly[i].y = _cdRound(fpoly[i].y);
}
- /* must disable transformation here, because line simulation use cxPixel */
- canvas->use_matrix = 0;
+ cdCanvasPoly(canvas, mode, poly, n);
- simPolyFill(canvas->simulation, poly, n);
+ free(poly);
+ }
+ break;
+ }
+}
- canvas->use_matrix = old_use_matrix;
- cdCanvasLineStyle(canvas, oldstyle);
- cdCanvasLineWidth(canvas, oldwidth);
+void cdSimMark(cdCanvas* canvas, int x, int y)
+{
+ int oldinteriorstyle = canvas->interior_style;
+ int oldlinestyle = canvas->line_style;
+ int oldlinewidth = canvas->line_width;
+ int size = canvas->mark_size;
+ int half_size = size/2;
+ int bottom = y-half_size;
+ int top = y+half_size;
+ int left = x-half_size;
+ int right = x+half_size;
+
+ if (canvas->interior_style != CD_SOLID &&
+ (canvas->mark_type == CD_CIRCLE ||
+ canvas->mark_type == CD_BOX ||
+ canvas->mark_type == CD_DIAMOND))
+ cdCanvasInteriorStyle(canvas, CD_SOLID);
+
+ if (canvas->line_style != CD_CONTINUOUS &&
+ (canvas->mark_type == CD_STAR ||
+ canvas->mark_type == CD_PLUS ||
+ canvas->mark_type == CD_X ||
+ canvas->mark_type == CD_HOLLOW_BOX ||
+ canvas->mark_type == CD_HOLLOW_CIRCLE ||
+ canvas->mark_type == CD_HOLLOW_DIAMOND))
+ cdCanvasLineStyle(canvas, CD_CONTINUOUS);
+
+ if (canvas->line_width != 1 &&
+ (canvas->mark_type == CD_STAR ||
+ canvas->mark_type == CD_PLUS ||
+ canvas->mark_type == CD_X ||
+ canvas->mark_type == CD_HOLLOW_BOX ||
+ canvas->mark_type == CD_HOLLOW_CIRCLE ||
+ canvas->mark_type == CD_HOLLOW_DIAMOND))
+ cdCanvasLineWidth(canvas, 1);
+
+ switch (canvas->mark_type)
+ {
+ case CD_STAR:
+ canvas->cxLine(canvas->ctxcanvas, left, bottom, right, top);
+ canvas->cxLine(canvas->ctxcanvas, left, top, right, bottom);
+ /* continue */
+ case CD_PLUS:
+ canvas->cxLine(canvas->ctxcanvas, left, y, right, y);
+ canvas->cxLine(canvas->ctxcanvas, x, bottom, x, top);
+ break;
+ case CD_X:
+ canvas->cxLine(canvas->ctxcanvas, left, bottom, right, top);
+ canvas->cxLine(canvas->ctxcanvas, left, top, right, bottom);
+ break;
+ case CD_HOLLOW_CIRCLE:
+ canvas->cxArc(canvas->ctxcanvas, x, y, size, size, 0, 360);
+ break;
+ case CD_HOLLOW_BOX:
+ canvas->cxRect(canvas->ctxcanvas, left, right, bottom, top);
+ break;
+ case CD_CIRCLE:
+ canvas->cxSector(canvas->ctxcanvas, x, y, size, size, 0, 360);
+ break;
+ case CD_BOX:
+ canvas->cxBox(canvas->ctxcanvas, left, right, bottom, top);
+ break;
+ case CD_HOLLOW_DIAMOND:
+ case CD_DIAMOND:
+ {
+ cdPoint poly[5]; /* leave room for one more point */
+ poly[0].x = left;
+ poly[0].y = y;
+ poly[1].x = x;
+ poly[1].y = top;
+ poly[2].x = right;
+ poly[2].y = y;
+ poly[3].x = x;
+ poly[3].y = bottom;
+
+ if (canvas->mark_type == CD_DIAMOND)
+ cdCanvasPoly(canvas, CD_FILL, poly, 4);
+ else
+ cdCanvasPoly(canvas, CD_CLOSED_LINES, poly, 4);
}
break;
}
+
+ if (canvas->interior_style != oldinteriorstyle &&
+ (canvas->mark_type == CD_CIRCLE ||
+ canvas->mark_type == CD_BOX ||
+ canvas->mark_type == CD_DIAMOND))
+ cdCanvasInteriorStyle(canvas, oldinteriorstyle);
+
+ if (canvas->line_style != oldlinestyle &&
+ (canvas->mark_type == CD_STAR ||
+ canvas->mark_type == CD_PLUS ||
+ canvas->mark_type == CD_X ||
+ canvas->mark_type == CD_HOLLOW_BOX ||
+ canvas->mark_type == CD_HOLLOW_CIRCLE ||
+ canvas->mark_type == CD_HOLLOW_DIAMOND))
+ cdCanvasLineStyle(canvas, oldlinestyle);
+
+ if (canvas->line_width != oldlinewidth &&
+ (canvas->mark_type == CD_STAR ||
+ canvas->mark_type == CD_PLUS ||
+ canvas->mark_type == CD_X ||
+ canvas->mark_type == CD_HOLLOW_BOX ||
+ canvas->mark_type == CD_HOLLOW_CIRCLE ||
+ canvas->mark_type == CD_HOLLOW_DIAMOND))
+ cdCanvasLineWidth(canvas, oldlinewidth);
+}
+
+void cdSimPutImageRectRGBA(cdCanvas* canvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, const unsigned char *a, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ int size, i, j, dst, src, *fx, *fy, rw, rh;
+ unsigned char *ar, *ag, *ab, al;
+ (void)ih;
+
+ size = w * h;
+ ar = (unsigned char*)malloc(size*3);
+ if (!ar) return;
+ ag = ar + size;
+ ab = ag + size;
+
+ canvas->cxGetImageRGB(canvas->ctxcanvas, ar, ag, ab, x, y, w, h);
+
+ rw = xmax-xmin+1;
+ rh = ymax-ymin+1;
+
+ fx = cdGetZoomTable(w, rw, xmin);
+ fy = cdGetZoomTable(h, rh, ymin);
+
+ for (j = 0; j < h; j++)
+ {
+ for (i = 0; i < w; i++)
+ {
+ dst = j * w + i;
+ src = fy[j] * iw + fx[i];
+ al = a[src];
+ ar[dst] = CD_ALPHA_BLEND(r[src], ar[dst], al);
+ ag[dst] = CD_ALPHA_BLEND(g[src], ag[dst], al);
+ ab[dst] = CD_ALPHA_BLEND(b[src], ab[dst], al);
+ }
+ }
+
+ canvas->cxPutImageRectRGB(canvas->ctxcanvas, w, h, ar, ag, ab, x, y, w, h, 0, 0, 0, 0);
+
+ free(ar);
+
+ free(fx);
+ free(fy);
+}
+
+void cdSimPutImageRectRGB(cdCanvas* canvas, int iw, int ih, const unsigned char *r, const unsigned char *g, const unsigned char *b, int x, int y, int w, int h, int xmin, int xmax, int ymin, int ymax)
+{
+ int height = ymax-ymin+1;
+ unsigned char* map;
+ int pal_size = 1L << canvas->bpp;
+ long colors[256];
+ (void)ih;
+
+ map = (unsigned char*)malloc(iw * height);
+ if (!map)
+ return;
+
+ if (pal_size == 2) /* probably a laser printer, use a gray image for better results */
+ cdRGB2Gray(iw, height, r+ymin*iw, g+ymin*iw, b+ymin*iw, map, colors);
+ else
+ cdRGB2Map(iw, height, r+ymin*iw, g+ymin*iw, b+ymin*iw, map, pal_size, colors);
+
+ canvas->cxPutImageRectMap(canvas->ctxcanvas, iw, height, map, colors, x, y, w, h, xmin, xmax, 0, height-1);
+
+ free(map);
+}
+
+
+/************************************************************************/
+
+#include "cd_truetype.h"
+#include "sim.h"
+
+static void cdSimPolyLine(cdCanvas* canvas, const cdPoint* poly, int n)
+{
+ int i, reset = 1, transform = 0;
+ int old_use_matrix = canvas->use_matrix;
+ int x1, y1, x2, y2;
+
+ if (canvas->use_matrix)
+ transform = 1;
+
+ /* disable line transformation */
+ canvas->use_matrix = 0;
+
+ /* prepare the line style for several lines */
+ if (simLineStyleNoReset)
+ {
+ reset = 0;
+ simLineStyleNoReset = 1;
+ }
+
+ x1 = poly[0].x;
+ y1 = poly[0].y;
+
+ if (transform)
+ cdMatrixTransformPoint(canvas->matrix, x1, y1, &x1, &y1);
+
+ for (i = 0; i < n-1; i++)
+ {
+ x2 = poly[i+1].x;
+ y2 = poly[i+1].y;
+
+ if (transform)
+ cdMatrixTransformPoint(canvas->matrix, x2, y2, &x2, &y2);
+
+ if(canvas->line_width > 1)
+ simLineThick(canvas, x1, y1, x2, y2);
+ else
+ simLineThin(canvas, x1, y1, x2, y2);
+
+ x1 = x2;
+ y1 = y2;
+ }
+
+ if (reset) simLineStyleNoReset = 0;
+ canvas->use_matrix = old_use_matrix;
}
+
+static void cdfSimPolyLine(cdCanvas* canvas, const cdfPoint* poly, int n)
+{
+ int i, reset = 1, transform = 0;
+ int old_use_matrix = canvas->use_matrix;
+ double x1, y1, x2, y2;
+ int last_xi_a = -65535,
+ last_yi_a = -65535,
+ last_xi_b = -65535,
+ last_yi_b = -65535;
+
+ if (canvas->use_matrix)
+ transform = 1;
+
+ /* disable line transformation */
+ canvas->use_matrix = 0;
+
+ /* prepare the line style for several lines */
+ if (simLineStyleNoReset)
+ {
+ reset = 0;
+ simLineStyleNoReset = 1;
+ }
+
+ x1 = poly[0].x;
+ y1 = poly[0].y;
+
+ if (transform)
+ cdfMatrixTransformPoint(canvas->matrix, x1, y1, &x1, &y1);
+
+ for (i = 0; i < n-1; i++)
+ {
+ x2 = poly[i+1].x;
+ y2 = poly[i+1].y;
+
+ if (transform)
+ cdfMatrixTransformPoint(canvas->matrix, x2, y2, &x2, &y2);
+
+ if(canvas->line_width > 1)
+ simfLineThick(canvas, x1, y1, x2, y2);
+ else
+ simfLineThin(canvas, x1, y1, x2, y2, &last_xi_a, &last_yi_a, &last_xi_b, &last_yi_b);
+
+ x1 = x2;
+ y1 = y2;
+ }
+
+ if (reset) simLineStyleNoReset = 0;
+ canvas->use_matrix = old_use_matrix;
+}
+
+static int sCheckIsBox(cdPoint* poly)
+{
+ if (poly[0].x == poly[1].x &&
+ poly[1].y == poly[2].y &&
+ poly[2].x == poly[3].x &&
+ poly[3].y == poly[0].y)
+ return 1;
+
+ if (poly[0].y == poly[1].y &&
+ poly[1].x == poly[2].x &&
+ poly[2].y == poly[3].y &&
+ poly[3].x == poly[0].x)
+ return 1;
+
+ return 0;
+}
+
+static void sGetBox(cdPoint* poly, int *xmin, int *xmax, int *ymin, int *ymax)
+{
+ int i;
+ *xmin = poly[0].x;
+ *xmax = poly[0].x;
+ *ymin = poly[0].y;
+ *ymax = poly[0].y;
+ for (i=1; i<4; i++)
+ {
+ if (poly[i].x < *xmin)
+ *xmin = poly[i].x;
+ if (poly[i].y < *ymin)
+ *ymin = poly[i].y;
+ if (poly[i].x > *xmax)
+ *xmax = poly[i].x;
+ if (poly[i].y > *ymin)
+ *ymax = poly[i].y;
+ }
+}
+
+static void cdSimPolyFill(cdCanvas* canvas, cdPoint* poly, int n)
+{
+ int old_use_matrix = canvas->use_matrix;
+
+ if (canvas->use_matrix)
+ {
+ int i;
+ for(i = 0; i < n; i++) /* can do that because poly is internal of the CD, and it will NOT be stored */
+ cdMatrixTransformPoint(canvas->matrix, poly[i].x, poly[i].y, &poly[i].x, &poly[i].y);
+ }
+
+ /* disable fill transformation */
+ canvas->use_matrix = 0;
+
+ if (n == 4 && sCheckIsBox(poly))
+ {
+ int xmin, xmax, ymin, ymax;
+ sGetBox(poly, &xmin, &xmax, &ymin, &ymax);
+ simFillHorizBox(canvas->simulation, xmin, xmax, ymin, ymax);
+ }
+ else
+ simPolyFill(canvas->simulation, poly, n);
+
+ canvas->use_matrix = old_use_matrix;
+}
+
diff --git a/cd/src/sim/truetype.h b/cd/src/sim/truetype.h
deleted file mode 100755
index 5675998..0000000
--- a/cd/src/sim/truetype.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/** \file
- * \brief Text and Font Simulation using FreeType library.
- *
- * See Copyright Notice in cd.h
- */
-
-#ifndef __TRUETYPE_H
-#define __TRUETYPE_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "ft2build.h"
-#include FT_FREETYPE_H
-
-/*
- In CD version 4.4 we start to use FreeType 2.
- Only TrueType font support is enabled.
-*/
-
-typedef struct _cdTT_Text
-{
- FT_Library library;
- FT_Face face;
-
- unsigned char* rgba_data;
- int rgba_data_size;
-
- int max_height;
- int max_width;
- int descent;
- int ascent;
-
-}cdTT_Text;
-
-cdTT_Text* cdTT_create(void);
-void cdTT_free(cdTT_Text * tt_text);
-int cdTT_load(cdTT_Text * tt_text, const char *font,int size, double xres, double yres);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* ifndef _CD_TRUETYPE_ */
-