summaryrefslogtreecommitdiff
path: root/src/sim/sim.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sim/sim.c')
-rw-r--r--src/sim/sim.c328
1 files changed, 328 insertions, 0 deletions
diff --git a/src/sim/sim.c b/src/sim/sim.c
new file mode 100644
index 0000000..0c657fa
--- /dev/null
+++ b/src/sim/sim.c
@@ -0,0 +1,328 @@
+/** \file
+ * \brief 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"
+#include "cd_truetype.h"
+#include "sim.h"
+
+
+static unsigned char SimHatchBits[6][8] = { /* [style][y] (8x8) */
+ {0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00}, /* CD_HORIZONTAL */
+ {0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, /* CD_VERTICAL */
+ {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}, /* CD_BDIAGONAL */
+ {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}, /* CD_FDIAGONAL */
+ {0x10, 0x10, 0x10, 0xFF, 0x10, 0x10, 0x10, 0x10}, /* CD_CROSS */
+ {0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81}};/* CD_DIAGCROSS */
+
+#define CalcYPat(y, h) (canvas->invert_yaxis? h-1-(y%h): y%h)
+#define CalcYHatch(y, h) (canvas->invert_yaxis? h-(y&h): y&h)
+
+void simFillDrawAAPixel(cdCanvas *canvas, int x, int y, unsigned short alpha_weigth)
+{
+ unsigned char aa_alpha;
+ long color, aa_color;
+
+ switch(canvas->interior_style)
+ {
+ default: /* CD_SOLID */
+ {
+ color = canvas->foreground;
+ break;
+ }
+ case CD_PATTERN:
+ {
+ long *pattern = canvas->pattern;
+ int yp = CalcYPat(y, canvas->pattern_h);
+ int xp = x % canvas->pattern_w;
+ color = pattern[canvas->pattern_w*yp + xp];
+ break;
+ }
+ case CD_HATCH:
+ {
+ unsigned char hatch = SimHatchBits[canvas->hatch_style][CalcYHatch(y, 7)];
+ unsigned char n = (unsigned char)(x&7);
+ simRotateHatchN(hatch, n);
+ if (hatch & 0x80)
+ color = canvas->foreground;
+ else if (canvas->back_opacity == CD_OPAQUE)
+ color = canvas->background;
+ else
+ return;
+ break;
+ }
+ case CD_STIPPLE:
+ {
+ unsigned char *stipple = canvas->stipple;
+ int yp = CalcYPat(y, canvas->stipple_h);
+ int xp = x % canvas->stipple_w;
+ if(stipple[canvas->stipple_w*yp + xp])
+ color = canvas->foreground;
+ else if (canvas->back_opacity == CD_OPAQUE)
+ color = canvas->background;
+ else
+ return;
+ break;
+ }
+ }
+
+ aa_alpha = (unsigned char)((alpha_weigth * cdAlpha(color)) / 255);
+ aa_color = cdEncodeAlpha(color, aa_alpha);
+ canvas->cxPixel(canvas->ctxcanvas, x, y, aa_color);
+}
+
+void simFillHorizLine(cdSimulation* simulation, int xmin, int y, int xmax)
+{
+ cdCanvas* canvas = simulation->canvas;
+
+ if(xmin > xmax)
+ _cdSwapInt(xmin, xmax);
+
+ switch(canvas->interior_style)
+ {
+ case CD_SOLID:
+ simulation->SolidLine(canvas, xmin,y,xmax);
+ break;
+ case CD_PATTERN:
+ simulation->PatternLine(canvas, xmin,xmax,y,canvas->pattern_w,
+ canvas->pattern +
+ canvas->pattern_w*CalcYPat(y, canvas->pattern_h));
+ break;
+ case CD_HATCH:
+ simulation->HatchLine(canvas, xmin,xmax,y,SimHatchBits[canvas->hatch_style][CalcYHatch(y, 7)]);
+ break;
+ case CD_STIPPLE:
+ simulation->StippleLine(canvas, xmin, xmax, y,
+ canvas->stipple_w,
+ canvas->stipple +
+ canvas->stipple_w*CalcYPat(y, canvas->stipple_h));
+ }
+}
+
+static void simSolidLine(cdCanvas* canvas, int xmin, int y, int xmax)
+{
+ /* cdpolySIM and cdboxSIM will set line attributes so this can work */
+ canvas->cxLine(canvas->ctxcanvas, xmin, y, xmax, y);
+}
+
+static void simPatternLine(cdCanvas* canvas, int xmin, int xmax, int y, int pw, const long *pattern)
+{
+ cdSimulation* simulation = canvas->simulation;
+ int x,i;
+ int xb;
+ long curColor, old_color;
+
+ i = xmin % pw;
+
+ old_color = canvas->foreground;
+
+ for (x = xmin; x <= xmax;)
+ {
+ if (i == pw)
+ i = 0;
+
+ curColor=pattern[i];
+ xb=x;
+
+ while(pattern[i]==curColor && (x <= xmax))
+ {
+ i++;
+ if (i == pw)
+ i = 0;
+ x++;
+ }
+
+ if(xb==x-1)
+ canvas->cxPixel(canvas->ctxcanvas, xb,y,curColor);
+ else
+ {
+ cdCanvasSetForeground(canvas, curColor);
+ simulation->SolidLine(canvas, xb,y,x-1);
+ }
+ }
+
+ cdCanvasSetForeground(canvas, old_color);
+}
+
+static void simStippleLine(cdCanvas* canvas, int xmin, int xmax, int y, int pw, const unsigned char *stipple)
+{
+ cdSimulation* simulation = canvas->simulation;
+ int x,xb,i;
+ long fgColor,bgColor;
+ int opacity;
+ int curCase;
+
+ fgColor = canvas->foreground;
+ opacity=canvas->back_opacity;
+
+ if(opacity==CD_OPAQUE)
+ {
+ bgColor=canvas->background;
+ cdCanvasSetForeground(canvas, fgColor);
+ for (x = xmin, i=xmin%pw ; x <= xmax;)
+ {
+ if(i==pw)
+ i=0;
+ xb=x;
+ curCase=stipple[i];
+ while (stipple[i]==curCase && (x<=xmax))
+ {
+ x++;
+ i++;
+ if(i==pw)
+ i=0;
+ }
+ if (curCase)
+ {
+ if(xb==x-1)
+ canvas->cxPixel(canvas->ctxcanvas, xb,y,fgColor);
+ else
+ simulation->SolidLine(canvas, xb,y,x-1);
+ }
+ }
+ cdCanvasSetForeground(canvas, bgColor);
+ for (x = xmin, i=xmin%pw ; x <= xmax;)
+ {
+ if(i==pw)
+ i=0;
+ xb=x;
+ curCase=stipple[i];
+ while (stipple[i]==curCase && (x<=xmax))
+ {
+ x++;
+ i++;
+ if(i==pw)
+ i=0;
+ }
+ if (!curCase)
+ {
+ if(xb==x-1)
+ canvas->cxPixel(canvas->ctxcanvas, xb,y,bgColor);
+ else
+ simulation->SolidLine(canvas, xb,y,x-1);
+ }
+ }
+ }
+ else
+ {
+ cdCanvasSetForeground(canvas, fgColor);
+ for (x = xmin,i=xmin%pw; x <= xmax;)
+ {
+ xb=x;
+ curCase=stipple[i];
+ while (stipple[i]==curCase && (x<=xmax))
+ {
+ i++;
+ x++;
+ if(i==pw)
+ i=0;
+ }
+ if(curCase)
+ {
+ if(xb==x-1)
+ canvas->cxPixel(canvas->ctxcanvas, xb,y,fgColor);
+ else
+ simulation->SolidLine(canvas, xb,y,x-1);
+ }
+ }
+ }
+ cdCanvasSetForeground(canvas, fgColor);
+}
+
+static void simHatchLine(cdCanvas* canvas, int xmin, int xmax, int y, unsigned char hatch)
+{
+ cdSimulation* simulation = canvas->simulation;
+ int x,xb;
+ int opacity, mask;
+ unsigned char startp, n;
+ long curColor, fgColor, bgColor;
+
+ n = (unsigned char)(xmin&7);
+ simRotateHatchN(hatch,n);
+ fgColor=canvas->foreground;
+ opacity=canvas->back_opacity;
+
+ if(opacity==CD_OPAQUE)
+ {
+ bgColor=canvas->background;
+ for (x = xmin; x <= xmax; x++)
+ {
+ curColor=(hatch&0x80)?fgColor:bgColor;
+
+ xb=x;
+ startp = hatch&0x80? 1: 0;
+ _cdRotateHatch(hatch);
+ while (startp == (hatch&0x80? 1: 0) && x <= xmax)
+ {
+ x++;
+ _cdRotateHatch(hatch);
+ }
+
+ if(xb==x)
+ canvas->cxPixel(canvas->ctxcanvas, xb,y,curColor);
+ else
+ {
+ cdCanvasSetForeground(canvas, curColor);
+ simulation->SolidLine(canvas, xb,y,x);
+ }
+ }
+ }
+ else
+ {
+ cdCanvasSetForeground(canvas, fgColor);
+ for (x = xmin; x <= xmax; x++)
+ {
+ mask=(hatch&0x80)?1:0;
+
+ xb=x;
+ startp = hatch&0x80? 1: 0;
+ _cdRotateHatch(hatch);
+ while (startp == (hatch&0x80? 1: 0) && x <= xmax)
+ {
+ x++;
+ _cdRotateHatch(hatch);
+ }
+
+ if(mask)
+ {
+ if(xb==x)
+ canvas->cxPixel(canvas->ctxcanvas, xb,y,fgColor);
+ else
+ simulation->SolidLine(canvas, xb,y,x);
+ }
+ }
+ }
+
+ cdCanvasSetForeground(canvas, fgColor);
+}
+
+cdSimulation* cdCreateSimulation(cdCanvas* canvas)
+{
+ cdSimulation* simulation = (cdSimulation*)malloc(sizeof(cdSimulation));
+ memset(simulation, 0, sizeof(cdSimulation));
+
+ simulation->canvas = canvas;
+
+ simulation->SolidLine = simSolidLine;
+ simulation->PatternLine = simPatternLine;
+ simulation->StippleLine = simStippleLine;
+ simulation->HatchLine = simHatchLine;
+
+ return simulation;
+}
+
+void cdKillSimulation(cdSimulation* simulation)
+{
+ if (simulation->tt_text) cdTT_free(simulation->tt_text);
+
+ memset(simulation, 0, sizeof(cdSimulation));
+ free(simulation);
+}