//swftools header files
#include "swfoutput.h"
#include "../lib/log.h"
+#include "../lib/gfxdevice.h"
+#include "gfxtools.h"
#include <math.h>
int width, int height, GfxImageColorMap *colorMap,
int *maskColors, GBool inlineImg);
- virtual GBool beginType3Char(GfxState *state,
- CharCode code, Unicode *u, int uLen);
+ virtual GBool beginType3Char(GfxState *state, double x, double y, double dx, double dy, CharCode code, Unicode *u, int uLen);
virtual void endType3Char(GfxState *state);
+ virtual void type3D0(GfxState *state, double wx, double wy);
+ virtual void type3D1(GfxState *state, double wx, double wy, double llx, double lly, double urx, double ury);
+
private:
void drawGeneralImage(GfxState *state, Object *ref, Stream *str,
int width, int height, GfxImageColorMap*colorMap, GBool invert,
- GBool inlineImg, int mask);
+ GBool inlineImg, int mask, int *maskColors);
int clipping[64];
int clippos;
//void SWFOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, GBool inlineImg) {printf("void SWFOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, int width, int height, GBool invert, GBool inlineImg) \n");}
//void SWFOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, GBool inlineImg) {printf("void SWFOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, int width, int height, GfxImageColorMap *colorMap, GBool inlineImg) \n");}
-static void free_outline(SWF_OUTLINE*outline)
-{
- while(outline) {
- SWF_OUTLINE*next = outline->link;
- free(outline);
- outline = next;
- }
-}
-static void dump_outline(SWF_OUTLINE*outline)
-{
- double x=0,y=0;
- while(outline) {
- double lastx=x,lasty=y;
- x += (outline->dest.x/(float)0xffff);
- y += (outline->dest.y/(float)0xffff);
- if(outline->type == SWF_PATHTYPE_MOVE) {
- msg("<trace> | moveto %f,%f", x,y);
- } else if(outline->type == SWF_PATHTYPE_LINE) {
- msg("<trace> | lineto: %f,%f\n",x,y);
- } else if(outline->type == SWF_PATHTYPE_BEZIER) {
- SWF_BEZIERSEGMENT*o2 = (SWF_BEZIERSEGMENT*)outline;
- float x1 = o2->C.x/(float)0xffff+lastx;
- float y1 = o2->C.y/(float)0xffff+lasty;
- float x2 = o2->B.x/(float)0xffff+lastx;
- float y2 = o2->B.y/(float)0xffff+lasty;
- msg("<trace> | spline: %f,%f -> %f,%f -> %f,%f\n",x1,y1,x2,y2,x,y);
- }
- outline = outline->link;
+void dump_outline(gfxline_t*line)
+{
+ while(line) {
+ if(line->type == gfx_moveTo) {
+ msg("<debug> | moveTo %.2f %.2f", line->x,line->y);
+ } else if(line->type == gfx_lineTo) {
+ msg("<debug> | lineTo %.2f %.2f", line->x,line->y);
+ } else if(line->type == gfx_splineTo) {
+ msg("<debug> | splineTo (%.2f %.2f) %.2f %.2f", line->sx,line->sy, line->x, line->y);
+ }
+ line = line->next;
}
}
-SWF_OUTLINE* gfxPath_to_SWF_OUTLINE(GfxState*state, GfxPath*path)
+gfxline_t* gfxPath_to_gfxline(GfxState*state, GfxPath*path, int closed)
{
int num = path->getNumSubpaths();
int s,t;
- bezierpathsegment*start,*last=0;
- bezierpathsegment*outline = start = (bezierpathsegment*)malloc(sizeof(bezierpathsegment));
int cpos = 0;
- double lastx=0,lasty=0;
+ double lastx=0,lasty=0,posx=0,posy=0;
+ int needsfix=0;
if(!num) {
msg("<warning> empty path");
- outline->type = SWF_PATHTYPE_MOVE;
- outline->dest.x = 0;
- outline->dest.y = 0;
- outline->link = 0;
- return (SWF_OUTLINE*)outline;
+ return 0;
}
+ gfxdrawer_t draw;
+ gfxdrawer_target_gfxline(&draw);
+
for(t = 0; t < num; t++) {
GfxSubpath *subpath = path->getSubpath(t);
int subnum = subpath->getNumPoints();
+ double bx=0,by=0,cx=0,cy=0;
for(s=0;s<subnum;s++) {
- double nx,ny;
- state->transform(subpath->getX(s),subpath->getY(s),&nx,&ny);
- int x = (int)((nx-lastx)*0xffff);
- int y = (int)((ny-lasty)*0xffff);
- if(s==0)
- {
- last = outline;
- outline->type = SWF_PATHTYPE_MOVE;
- outline->dest.x = x;
- outline->dest.y = y;
- outline->link = (SWF_OUTLINE*)malloc(sizeof(bezierpathsegment));
- outline = (bezierpathsegment*)outline->link;
+ double x,y;
+ state->transform(subpath->getX(s),subpath->getY(s),&x,&y);
+ if(s==0) {
+ if(closed && needsfix && (fabs(posx-lastx)+fabs(posy-lasty))>0.001) {
+ draw.lineTo(&draw, lastx, lasty);
+ }
+ draw.moveTo(&draw, x,y);
+ posx = lastx = x;
+ posy = lasty = y;
cpos = 0;
- lastx = nx;
- lasty = ny;
- }
- else if(subpath->getCurve(s) && !cpos)
- {
- outline->B.x = x;
- outline->B.y = y;
+ needsfix = 0;
+ } else if(subpath->getCurve(s) && cpos==0) {
+ bx = x;
+ by = y;
cpos = 1;
- }
- else if(subpath->getCurve(s) && cpos)
- {
- outline->C.x = x;
- outline->C.y = y;
+ } else if(subpath->getCurve(s) && cpos==1) {
+ cx = x;
+ cy = y;
cpos = 2;
- }
- else
- {
- last = outline;
- outline->dest.x = x;
- outline->dest.y = y;
- outline->type = cpos?SWF_PATHTYPE_BEZIER:SWF_PATHTYPE_LINE;
- outline->link = (SWF_OUTLINE*)malloc(sizeof(bezierpathsegment));
- outline = (bezierpathsegment*)outline->link;
+ } else {
+ posx = x;
+ posy = y;
+ if(cpos==0) {
+ draw.lineTo(&draw, x,y);
+ } else {
+ gfxdraw_cubicTo(&draw, bx,by, cx,cy, x,y);
+ }
+ needsfix = 1;
cpos = 0;
- lastx = nx;
- lasty = ny;
}
}
}
- if(last->link) {free(last->link);}
- last->link = 0;
-
- return (SWF_OUTLINE*)start;
+ /* fix non-closed lines */
+ if(closed && needsfix && (fabs(posx-lastx)+fabs(posy-lasty))>0.001) {
+ draw.lineTo(&draw, lastx, lasty);
+ }
+ gfxline_t*result = (gfxline_t*)draw.result(&draw);
+ return result;
}
+
/*----------------------------------------------------------------------------
* Primitive Graphic routines
*----------------------------------------------------------------------------*/
int lineJoin = state->getLineJoin(); // 0=miter, 1=round 2=bevel
double miterLimit = state->getMiterLimit();
double width = state->getTransformedLineWidth();
- struct swfmatrix m;
+
GfxRGB rgb;
double opaq = state->getStrokeOpacity();
- state->getStrokeRGB(&rgb);
-
- m.m11 = 1; m.m21 = 0; m.m22 = 1;
- m.m12 = 0; m.m13 = 0; m.m23 = 0;
- SWF_OUTLINE*outline = gfxPath_to_SWF_OUTLINE(state, path);
-
- if(getLogLevel() >= LOGLEVEL_TRACE) {
- msg("<trace> stroke\n");
- dump_outline(outline);
- }
-
- lineJoin = 1; // other line joins are not yet supported by the swf encoder
- // TODO: support bevel joints
+ if(type3active)
+ state->getFillRGB(&rgb);
+ else
+ state->getStrokeRGB(&rgb);
+ gfxcolor_t col;
+ col.r = (unsigned char)(rgb.r*255);
+ col.g = (unsigned char)(rgb.g*255);
+ col.b = (unsigned char)(rgb.b*255);
+ col.a = (unsigned char)(opaq*255);
+
+ gfx_capType capType = gfx_capRound;
+ if(lineCap == 0) capType = gfx_capButt;
+ else if(lineCap == 1) capType = gfx_capRound;
+ else if(lineCap == 2) capType = gfx_capSquare;
- if(((lineCap==1) && (lineJoin==1)) || width<=caplinewidth) {
- /* FIXME- if the path is smaller than 2 segments, we could ignore
- lineJoin */
- swfoutput_setdrawmode(&output, DRAWMODE_STROKE);
- swfoutput_drawpath(&output, outline, &m);
- } else {
- swfoutput_setfillcolor(&output, (char)(rgb.r*255), (char)(rgb.g*255),
- (char)(rgb.b*255), (char)(opaq*255));
+ gfx_joinType joinType = gfx_joinRound;
+ if(lineJoin == 0) joinType = gfx_joinMiter;
+ else if(lineJoin == 1) joinType = gfx_joinRound;
+ else if(lineJoin == 2) joinType = gfx_joinBevel;
- //swfoutput_setlinewidth(&output, 1.0); //only for debugging
- //swfoutput_setstrokecolor(&output, 0, 255, 0, 255); //likewise, see below
- //swfoutput_setfillcolor(&output, 255, 0, 0, 255); //likewise, see below
+ gfxline_t*line= gfxPath_to_gfxline(state, path, 0);
+
+ int dashnum = 0;
+ double dashphase = 0;
+ double * ldash = 0;
+ state->getLineDash(&ldash, &dashnum, &dashphase);
+
+ if(dashnum && ldash) {
+ float * dash = (float*)malloc(sizeof(float)*(dashnum+1));
+ int t;
+ double cut = 0;
+ int fixzero = 0;
+ msg("<trace> %d dashes", dashnum);
+ msg("<trace> | phase: %f", dashphase);
+ for(t=0;t<dashnum;t++) {
+ dash[t] = ldash[t];
+ msg("<trace> | d%-3d: %f", t, ldash[t]);
+ }
+ dash[dashnum] = -1;
+ if(getLogLevel() >= LOGLEVEL_TRACE) {
+ dump_outline(line);
+ }
- swfoutput_drawpath2poly(&output, outline, &m, lineJoin, lineCap, width, miterLimit);
- updateLineWidth(state); //reset
- updateStrokeColor(state); //reset
- updateFillColor(state); //reset
+ gfxline_t*line2 = gfxtool_dash_line(line, dash, dashphase);
+ gfxline_free(line);
+ line = line2;
+ msg("<trace> After dashing:");
}
- free_outline(outline);
+
+ if(getLogLevel() >= LOGLEVEL_TRACE) {
+ double gray;
+ state->getStrokeGray(&gray);
+ msg("<trace> stroke width=%f join=%s cap=%s dashes=%d color=%02x%02x%02x%02x gray=%f\n",
+ width,
+ lineJoin==0?"miter": (lineJoin==1?"round":"bevel"),
+ lineCap==0?"butt": (lineJoin==1?"round":"square"),
+ dashnum,
+ col.r,col.g,col.b,col.a,
+ gray
+ );
+ dump_outline(line);
+ }
+
+ swfoutput_drawgfxline(&output, line, width, &col, capType, joinType, miterLimit);
+ gfxline_free(line);
}
void SWFOutputDev::fill(GfxState *state)
{
GfxPath * path = state->getPath();
- struct swfmatrix m;
- m.m11 = 1; m.m21 = 0; m.m22 = 1;
- m.m12 = 0; m.m13 = 0; m.m23 = 0;
- SWF_OUTLINE*outline = gfxPath_to_SWF_OUTLINE(state, path);
+ double opaq = state->getFillOpacity();
+ GfxRGB rgb;
+ state->getFillRGB(&rgb);
+ gfxcolor_t col;
+ col.r = (unsigned char)(rgb.r*255);
+ col.g = (unsigned char)(rgb.g*255);
+ col.b = (unsigned char)(rgb.b*255);
+ col.a = (unsigned char)(opaq*255);
+
+ gfxline_t*line= gfxPath_to_gfxline(state, path, 1);
if(getLogLevel() >= LOGLEVEL_TRACE) {
- msg("<trace> fill\n");
- dump_outline(outline);
+ msg("<trace> fill %02x%02x%02x%02x\n", col.r, col.g, col.b, col.a);
+ dump_outline(line);
}
- swfoutput_setdrawmode(&output, DRAWMODE_FILL);
- swfoutput_drawpath(&output, outline, &m);
- free_outline(outline);
+ swfoutput_fillgfxline(&output, line, &col);
+ gfxline_free(line);
}
void SWFOutputDev::eoFill(GfxState *state)
{
GfxPath * path = state->getPath();
- struct swfmatrix m;
- m.m11 = 1; m.m21 = 0; m.m22 = 1;
- m.m12 = 0; m.m13 = 0; m.m23 = 0;
- SWF_OUTLINE*outline = gfxPath_to_SWF_OUTLINE(state, path);
+ double opaq = state->getFillOpacity();
+ GfxRGB rgb;
+ state->getFillRGB(&rgb);
+ gfxcolor_t col;
+ col.r = (unsigned char)(rgb.r*255);
+ col.g = (unsigned char)(rgb.g*255);
+ col.b = (unsigned char)(rgb.b*255);
+ col.a = (unsigned char)(opaq*255);
+
+ gfxline_t*line= gfxPath_to_gfxline(state, path, 1);
if(getLogLevel() >= LOGLEVEL_TRACE) {
msg("<trace> eofill\n");
- dump_outline(outline);
+ dump_outline(line);
}
- swfoutput_setdrawmode(&output, DRAWMODE_EOFILL);
- swfoutput_drawpath(&output, outline, &m);
- free_outline(outline);
+ swfoutput_fillgfxline(&output, line, &col);
+ gfxline_free(line);
}
void SWFOutputDev::clip(GfxState *state)
{
GfxPath * path = state->getPath();
- struct swfmatrix m;
- m.m11 = 1; m.m22 = 1;
- m.m12 = 0; m.m21 = 0;
- m.m13 = 0; m.m23 = 0;
- SWF_OUTLINE*outline = gfxPath_to_SWF_OUTLINE(state, path);
+ gfxline_t*line = gfxPath_to_gfxline(state, path, 1);
if(getLogLevel() >= LOGLEVEL_TRACE) {
msg("<trace> clip\n");
- dump_outline(outline);
+ dump_outline(line);
}
- swfoutput_startclip(&output, outline, &m);
+ swfoutput_startclip(&output, line);
clipping[clippos] ++;
- free_outline(outline);
+ gfxline_free(line);
}
void SWFOutputDev::eoClip(GfxState *state)
{
GfxPath * path = state->getPath();
- struct swfmatrix m;
- m.m11 = 1; m.m21 = 0; m.m22 = 1;
- m.m12 = 0; m.m13 = 0; m.m23 = 0;
- SWF_OUTLINE*outline = gfxPath_to_SWF_OUTLINE(state, path);
+ gfxline_t*line = gfxPath_to_gfxline(state, path, 1);
if(getLogLevel() >= LOGLEVEL_TRACE) {
msg("<trace> eoclip\n");
- dump_outline(outline);
+ dump_outline(line);
}
- swfoutput_startclip(&output, outline, &m);
+ swfoutput_startclip(&output, line);
clipping[clippos] ++;
- free_outline(outline);
+ gfxline_free(line);
}
/* pass through functions for swf_output */
// check for invisible text -- this is used by Acrobat Capture
if ((state->getRender() & 3) == 3)
return;
+ GfxRGB rgb;
+ double opaq = state->getFillOpacity();
+ state->getFillRGB(&rgb);
+ gfxcolor_t col;
+ col.r = (unsigned char)(rgb.r*255);
+ col.g = (unsigned char)(rgb.g*255);
+ col.b = (unsigned char)(rgb.b*255);
+ col.a = (unsigned char)(opaq*255);
+
Gushort *CIDToGIDMap = 0;
GfxFont*font = state->getFont();
if (CIDToGIDMap) {
msg("<debug> drawChar(%f, %f, c='%c' (%d), GID=%d, u=%d <%d>) CID=%d name=\"%s\"\n", x, y, (c&127)>=32?c:'?', c, CIDToGIDMap[c], u, uLen, font->isCIDFont(), FIXNULL(name));
- swfoutput_drawchar(&output, x1, y1, name, CIDToGIDMap[c], u);
+ swfoutput_drawchar(&output, x1, y1, name, CIDToGIDMap[c], u, &col);
} else {
msg("<debug> drawChar(%f,%f,c='%c' (%d), u=%d <%d>) CID=%d name=\"%s\"\n",x,y,(c&127)>=32?c:'?',c,u, uLen, font->isCIDFont(), FIXNULL(name));
- swfoutput_drawchar(&output, x1, y1, name, c, u);
+ swfoutput_drawchar(&output, x1, y1, name, c, u, &col);
}
}
void SWFOutputDev::endString(GfxState *state) {
}
-
-GBool SWFOutputDev::beginType3Char(GfxState *state,
- CharCode code, Unicode *u, int uLen)
+/* the logic seems to be as following:
+ first, beginType3Char is called, with the charcode and the coordinates.
+ if this function returns true, it already knew about the char and has now drawn it.
+ if the function returns false, it's a new char, and type3D1 is called with some parameters-
+ the all draw operations until endType3Char are part of the char (which in this moment is
+ at the position first passed to beginType3Char). the char ends with endType3Char.
+
+ The drawing operations between beginType3Char and endType3Char are somewhat different to
+ the normal ones. For example, the fillcolor equals the stroke color.
+*/
+
+GBool SWFOutputDev::beginType3Char(GfxState *state, double x, double y, double dx, double dy, CharCode code, Unicode *u, int uLen)
{
msg("<debug> beginType3Char %d, %08x, %d", code, *u, uLen);
type3active = 1;
- /* the character itself is going to be passed using
- drawImageMask() */
+ /* the character itself is going to be passed using the draw functions */
return gFalse; /* gTrue= is_in_cache? */
}
+void SWFOutputDev::type3D0(GfxState *state, double wx, double wy) {
+ msg("<debug> type3D0 width=%f height=%f", wx, wy);
+}
+void SWFOutputDev::type3D1(GfxState *state, double wx, double wy, double llx, double lly, double urx, double ury) {
+ msg("<debug> type3D1 width=%f height=%f bbox=(%f,%f,%f,%f)", wx, wy,
+ llx,lly,urx,ury);
+}
+
void SWFOutputDev::endType3Char(GfxState *state)
{
type3active = 0;
void SWFOutputDev::updateLineWidth(GfxState *state)
{
double width = state->getTransformedLineWidth();
- swfoutput_setlinewidth(&output, width);
+ //swfoutput_setlinewidth(&output, width);
}
void SWFOutputDev::updateLineCap(GfxState *state)
double opaq = state->getFillOpacity();
state->getFillRGB(&rgb);
- swfoutput_setfillcolor(&output, (char)(rgb.r*255), (char)(rgb.g*255),
- (char)(rgb.b*255), (char)(opaq*255));
+ //swfoutput_setfillcolor(&output, (char)(rgb.r*255), (char)(rgb.g*255), (char)(rgb.b*255), (char)(opaq*255));
}
void SWFOutputDev::updateStrokeColor(GfxState *state)
GfxRGB rgb;
double opaq = state->getStrokeOpacity();
state->getStrokeRGB(&rgb);
-
- swfoutput_setstrokecolor(&output, (char)(rgb.r*255), (char)(rgb.g*255),
- (char)(rgb.b*255), (char)(opaq*255));
+ //swfoutput_setstrokecolor(&output, (char)(rgb.r*255), (char)(rgb.g*255), (char)(rgb.b*255), (char)(opaq*255));
}
void FoFiWrite(void *stream, char *data, int len)
msg("<notice> Collection: %s", c.getCString());
}*/
- if (font->getType() == fontType1C ||
- font->getType() == fontCIDType0C) {
+ if (font->getType() == fontType1C) {
if (!(fontBuf = font->readEmbFontFile(xref, &fontLen))) {
fclose(f);
msg("<error> Couldn't read embedded font file");
void SWFOutputDev::drawGeneralImage(GfxState *state, Object *ref, Stream *str,
int width, int height, GfxImageColorMap*colorMap, GBool invert,
- GBool inlineImg, int mask)
+ GBool inlineImg, int mask, int*maskColors)
{
FILE *fi;
int c;
}
int x,y;
-
+
if(colorMap->getNumPixelComps()!=1 || str->getKind()==strDCT) {
RGBA*pic=new RGBA[width*height];
for (y = 0; y < height; ++y) {
for(t=0;t<256;t++) {
pixBuf[0] = t;
colorMap->getRGB(pixBuf, &rgb);
- pal[t].r = (U8)(rgb.r * 255 + 0.5);
- pal[t].g = (U8)(rgb.g * 255 + 0.5);
- pal[t].b = (U8)(rgb.b * 255 + 0.5);
- pal[t].a = 255;//(U8)(rgb.b * 255 + 0.5);
+ /*if(maskColors && *maskColors==t) {
+ msg("<notice> Color %d is transparent", t);
+ if (imgData->maskColors) {
+ *alpha = 0;
+ for (i = 0; i < imgData->colorMap->getNumPixelComps(); ++i) {
+ if (pix[i] < imgData->maskColors[2*i] ||
+ pix[i] > imgData->maskColors[2*i+1]) {
+ *alpha = 1;
+ break;
+ }
+ }
+ } else {
+ *alpha = 1;
+ }
+ if(!*alpha) {
+ pal[t].r = 0;
+ pal[t].g = 0;
+ pal[t].b = 0;
+ pal[t].a = 0;
+ }
+ } else*/ {
+ pal[t].r = (U8)(rgb.r * 255 + 0.5);
+ pal[t].g = (U8)(rgb.g * 255 + 0.5);
+ pal[t].b = (U8)(rgb.b * 255 + 0.5);
+ pal[t].a = 255;//(U8)(rgb.b * 255 + 0.5);
+ }
}
for (y = 0; y < height; ++y) {
for (x = 0; x < width; ++x) {
GBool inlineImg)
{
msg("<verbose> drawImageMask %dx%d, invert=%d inline=%d", width, height, invert, inlineImg);
- drawGeneralImage(state,ref,str,width,height,0,invert,inlineImg,1);
+ drawGeneralImage(state,ref,str,width,height,0,invert,inlineImg,1, 0);
}
void SWFOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
if(colorMap)
msg("<verbose> colorMap pixcomps:%d bits:%d mode:%d\n", colorMap->getNumPixelComps(),
colorMap->getBits(),colorMap->getColorSpace()->getMode());
- drawGeneralImage(state,ref,str,width,height,colorMap,0,inlineImg,0);
+ drawGeneralImage(state,ref,str,width,height,colorMap,0,inlineImg,0,maskColors);
}
SWFOutputDev*output = 0;