#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;
+
+ 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)
gfxline_t*line= gfxPath_to_gfxline(state, path, 0, user_movex + clipmovex, user_movey + clipmovey);
if(getLogLevel() >= LOGLEVEL_TRACE) {
- msg("<trace> cliptostrokepath");
+ double width = state->getTransformedLineWidth();
+ msg("<trace> cliptostrokepath width=%f", width);
dump_outline(line);
}
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)
}
-gfxfont_t* createGfxFont(GfxFont*xpdffont, FontInfo*src, double config_fontquality)
+static gfxfont_t* createGfxFont(GfxFont*xpdffont, FontInfo*src, double config_fontquality)
{
gfxfont_t*font = (gfxfont_t*)malloc(sizeof(gfxfont_t));
memset(font, 0, sizeof(gfxfont_t));
font->glyphs = (gfxglyph_t*)malloc(sizeof(gfxglyph_t)*src->num_glyphs);
memset(font->glyphs, 0, sizeof(gfxglyph_t)*src->num_glyphs);
- font->id = strdup(getFontID(xpdffont));
+ font->id = 0;
int t;
double quality = (INTERNAL_FONT_SIZE * 200 / config_fontquality) / src->max_size;
unsigned char*newdata;
int x,y;
newdata= (unsigned char*)malloc(newwidth*newheight);
- double fx = (double)(width)/newwidth;
- double fy = (double)(height)/newheight;
+ double fx = ((double)width)/newwidth;
+ double fy = ((double)height)/newheight;
double px = 0;
int blocksize = (int)(8192/(fx*fy));
int r = 8192*256/palettesize;
double ex = px + fx;
int fromx = (int)px;
int tox = (int)ex;
- int xweight1 = (int)(((fromx+1)-px)*256);
+ int xweight1 = (int)((1-(px-fromx))*256);
int xweight2 = (int)((ex-tox)*256);
double py =0;
for(y=0;y<newheight;y++) {
double ey = py + fy;
int fromy = (int)py;
int toy = (int)ey;
- int yweight1 = (int)(((fromy+1)-py)*256);
+ int yweight1 = (int)((1-(py-fromy))*256);
int yweight2 = (int)((ey-toy)*256);
int a = 0;
int xx,yy;
+ if(tox>=width)
+ tox = width-1;
+ if(toy>=height)
+ toy = height-1;
for(xx=fromx;xx<=tox;xx++)
for(yy=fromy;yy<=toy;yy++) {
int b = 1-data[width*yy+xx];
/* TODO: pass image_dpi to device instead */
dev->setparameter(dev, "next_bitmap_is_jpeg", "1");
+ dump_outline(&p1);
dev->fillbitmap(dev, &p1, &img, &m, 0);
}
this->transformXY(state, 1, 0, &x3, &y3);
this->transformXY(state, 1, 1, &x4, &y4);
+ if(type3active) {
+ /* as type 3 bitmaps are antialized, we need to place them
+ at integer coordinates, otherwise flash player's antializing
+ will kick in and make everything blurry */
+ x1 = (int)(x1);y1 = (int)(y1);
+ x2 = (int)(x2);y2 = (int)(y2);
+ x3 = (int)(x3);y3 = (int)(y3);
+ x4 = (int)(x4);y4 = (int)(y4);
+ }
+
if(!pbminfo && !(str->getKind()==strDCT)) {
if(!type3active) {
msg("<notice> File contains pbm pictures %s",mask?"(masked)":"");
delete imgStr;
return;
}
-
+
width = realwidth;
height = realheight;
- free(pic);
+ delete[] pic;
pic = pic2;
/* make a black/white palette */
pal[t].b = colToByte(rgb.b);
pal[t].a = (unsigned char)(t*r);
}
+
}
gfxcolor_t*pic2 = new gfxcolor_t[width*height];
}
}
drawimagelossless(device, pic2, width, height, x1,y1,x2,y2,x3,y3,x4,y4);
- free(pic2);
- free(pic);
+ delete[] pic2;
+ delete[] pic;
delete imgStr;
if(maskbitmap) free(maskbitmap);
return;
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");
}
gfxresult_t*mask = states[statepos].softmaskrecording;
- gfxresult_t*below = this->device->finish(this->device);
+ gfxresult_t*below = this->device->finish(this->device);free(this->device);
this->device = states[statepos].olddevice;
/* get outline of all objects below the soft mask */