/** \file * \brief Simulation Base Driver * * See Copyright Notice in cd.h */ #include #include #include #include #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, canvas->foreground); 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)); } } void simFillHorizBox(cdSimulation* simulation, int xmin, int xmax, int ymin, int ymax) { 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) { cdSimulation* simulation = canvas->simulation; int x,i; int xb; long curColor; i = xmin % pw; 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 simulation->SolidLine(canvas, xb,y,x-1, curColor); } } 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; 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,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,bgColor); else simulation->SolidLine(canvas, xb,y,x-1,bgColor); } } } else { 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,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 simulation->SolidLine(canvas, xb,y,x, curColor); } } else { 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,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); }