#include "../devices/polyops.h"
#include "../devices/render.h"
-#include "../art/libart.h"
-
#include "../png.h"
#include "fonts.h"
#include <math.h>
+#define SQRT2 1.41421356237309504880
+
typedef struct _fontfile
{
const char*filename;
this->pages = 0;
this->pagebuflen = 0;
this->pagepos = 0;
- this->config_convertgradients=0;
+ this->config_convertgradients=1;
this->config_break_on_warning=0;
this->config_remapunicode=0;
this->config_transparent=0;
device->endclip(device);
outer_clip_box = 0;
}
+ this->dashPattern = 0;
+ /* notice: we're not fully done yet with this page- there might still be
+ a few calls to drawLink() yet to come */
}
+static inline double sqr(double x) {return x*x;}
+
#define STROKE_FILL 1
#define STROKE_CLIP 2
void GFXOutputDev::strokeGfxline(GfxState *state, gfxline_t*line, int flags)
col.g = colToByte(rgb.g);
col.b = colToByte(rgb.b);
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(lineJoin == 1) joinType = gfx_joinRound;
else if(lineJoin == 2) joinType = gfx_joinBevel;
- int dashnum = 0;
- double dashphase = 0;
- double * ldash = 0;
- state->getLineDash(&ldash, &dashnum, &dashphase);
-
gfxline_t*line2 = 0;
- if(dashnum && ldash) {
- float * dash = (float*)malloc(sizeof(float)*(dashnum+1));
+ if(this->dashLength && this->dashPattern) {
+ float * dash = (float*)malloc(sizeof(float)*(this->dashLength+1));
int t;
- msg("<trace> %d dashes", dashnum);
- msg("<trace> | phase: %f", dashphase);
- for(t=0;t<dashnum;t++) {
- dash[t] = (float)ldash[t];
- msg("<trace> | d%-3d: %f", t, ldash[t]);
+
+ /* try to find out how much the transformation matrix would
+ stretch the dashes, and factor that into the dash lengths.
+ This is not the entirely correct approach- it would be
+ better to first convert the path to an unscaled version,
+ then apply dashing, and then transform the path using
+ the current transformation matrix. However there are few
+ PDFs which actually stretch a dashed path in a non-orthonormal
+ way */
+ double tx1, ty1, tx2, ty2;
+ this->transformXY(state, 0, 0, &tx1, &ty1);
+ this->transformXY(state, 1, 1, &tx2, &ty2);
+ double f = sqrt(sqr(tx2-tx1)+sqr(ty2-ty1)) / SQRT2;
+
+ f = 1.0; //disable dash length transform for now
+
+ msg("<trace> %d dashes", this->dashLength);
+ msg("<trace> | phase: %f", this->dashStart);
+ for(t=0;t<this->dashLength;t++) {
+ dash[t] = (float)this->dashPattern[t] * f;
+ msg("<trace> | d%-3d: %f", t, this->dashPattern[t]);
}
- dash[dashnum] = -1;
+ dash[this->dashLength] = -1;
if(getLogLevel() >= LOGLEVEL_TRACE) {
dump_outline(line);
}
- line2 = gfxtool_dash_line(line, dash, (float)dashphase);
+ line2 = gfxtool_dash_line(line, dash, (float)(this->dashStart*f));
line = line2;
free(dash);
msg("<trace> After dashing:");
width,
lineJoin==0?"miter": (lineJoin==1?"round":"bevel"),
lineCap==0?"butt": (lineJoin==1?"round":"square"),
- dashnum,
+ this->dashLength,
col.r,col.g,col.b,col.a
);
dump_outline(line);
} else {
device->fill(device, gfxline, &col);
}
- free(gfxline);
+ gfxline_free(gfxline);
gfxpoly_free(poly);
} else {
if(flags&STROKE_CLIP)
states[statepos].clipbbox.ymin = x1;
states[statepos].clipbbox.xmax = x2;
states[statepos].clipbbox.ymax = y2;
+
+ this->dashPattern = 0;
+ this->dashLength = 0;
+ this->dashStart = 0;
}
}
void GFXOutputDev::saveState(GfxState *state) {
- dbg("saveState");dbgindent+=2;
+ dbg("saveState"); dbgindent+=2;
msg("<trace> saveState");
updateAll(state);
}
statepos--;
}
+
+void GFXOutputDev::updateLineDash(GfxState *state)
+{
+ state->getLineDash(&this->dashPattern, &this->dashLength, &this->dashStart);
+ msg("<debug> updateLineDash, %d dashes", this->dashLength);
+ if(!this->dashLength) {
+ this->dashPattern = 0;
+ }
+}
void GFXOutputDev::updateLineWidth(GfxState *state)
{
double width = state->getTransformedLineWidth();
- //swfoutput_setlinewidth(&device, width);
}
void GFXOutputDev::updateLineCap(GfxState *state)
GBool forSoftMask)
{
const char*colormodename = "";
-
+
if(blendingColorSpace) {
colormodename = GfxColorSpace::getColorSpaceModeName(blendingColorSpace->getMode());
}
- dbg("beginTransparencyGroup %.1f/%.1f/%.1f/%.1f %s isolated=%d knockout=%d forsoftmask=%d", bbox[0],bbox[1],bbox[2],bbox[3], colormodename, isolated, knockout, forSoftMask);
+ dbg("beginTransparencyGroup device=%08x %.1f/%.1f/%.1f/%.1f %s isolated=%d knockout=%d forsoftmask=%d", device, bbox[0],bbox[1],bbox[2],bbox[3], colormodename, isolated, knockout, forSoftMask);
msg("<verbose> beginTransparencyGroup %.1f/%.1f/%.1f/%.1f %s isolated=%d knockout=%d forsoftmask=%d", bbox[0],bbox[1],bbox[2],bbox[3], colormodename, isolated, knockout, forSoftMask);
//states[statepos].createsoftmask |= forSoftMask;
void GFXOutputDev::setSoftMask(GfxState *state, double *bbox, GBool alpha, Function *transferFunc, GfxColor *rgb)
{
+ if(states[statepos].softmask) {
+ /* shouldn't happen, but *does* happen */
+ clearSoftMask(state);
+ }
+
/* alpha = 1: retrieve mask values from alpha layer
alpha = 0: retrieve mask values from luminance */
+
dbg("setSoftMask %.1f/%.1f/%.1f/%.1f alpha=%d backdrop=%02x%02x%02x",
bbox[0], bbox[1], bbox[2], bbox[3], alpha, colToByte(rgb->c[0]), colToByte(rgb->c[1]), colToByte(rgb->c[2]));
msg("<verbose> setSoftMask %.1f/%.1f/%.1f/%.1f alpha=%d backdrop=%02x%02x%02x",
this->device = (gfxdevice_t*)rfx_calloc(sizeof(gfxdevice_t));
gfxdevice_record_init(this->device);
- dbg("softmaskrecording is %08x at statepos %d\n", states[statepos].softmaskrecording, statepos);
+ dbg("softmaskrecording is %08x (dev=%08x) at statepos %d\n", states[statepos].softmaskrecording, this->device, statepos);
states[statepos].softmask = 1;
states[statepos].softmask_alpha = alpha;
return;
states[statepos].softmask = 0;
dbg("clearSoftMask statepos=%d", statepos);
- msg("<verbose> clearSoftMask");
+ msg("<verbose> clearSoftMask statepos=%d", statepos);
if(!states[statepos].softmaskrecording || strcmp(this->device->name, "record")) {
msg("<error> Error in softmask/tgroup ordering");