#include <assert.h>
#include "../gfxdevice.h"
#include "../gfxtools.h"
+#include "../gfxfont.h"
#include "../types.h"
#include "../bitio.h"
#include "../log.h"
/* ------------------------------- replaying --------------------------------- */
-static void replay(struct _gfxdevice*dev, gfxdevice_t*out, reader_t*r)
+static void replay(struct _gfxdevice*dev, gfxdevice_t*out, reader_t*r, gfxfontlist_t**fontlist)
{
internal_t*i = 0;
if(dev) {
i = (internal_t*)dev->internal;
}
+ gfxfontlist_t*_fontlist=0;
+ if(!fontlist) {
+ fontlist = &_fontlist;
+ }
state_t state;
memset(&state, 0, sizeof(state));
- gfxfontlist_t* fontlist = gfxfontlist_create();
-
while(1) {
unsigned char op;
if(r->read(r, &op, 1)!=1)
case OP_ADDFONT: {
msg("<trace> replay: ADDFONT out=%08x(%s)", out, out->name);
gfxfont_t*font = readFont(r, &state);
- fontlist = gfxfontlist_addfont(fontlist, font);
- out->addfont(out, font);
+ if(!gfxfontlist_hasfont(*fontlist, font)) {
+ printf("%08x / %08x: font %s is new\n", out, *fontlist, font->id);
+ *fontlist = gfxfontlist_addfont(*fontlist, font);
+ out->addfont(out, font);
+ } else {
+ gfxfont_free(font);
+ }
break;
}
case OP_DRAWCHAR: {
gfxcolor_t color = read_color(r, &state, op, flags);
gfxmatrix_t matrix = read_matrix(r, &state, op, flags);
- gfxfont_t*font = id?gfxfontlist_findfont(fontlist, id):0;
+ gfxfont_t*font = id?gfxfontlist_findfont(*fontlist, id):0;
if(i && !font) {
font = gfxfontlist_findfont(i->fontlist, id);
}
}
finish:
r->dealloc(r);
- /* problem: if we just replayed into a device which stores the
- font for later use (the record device itself is a nice example),
- then we can't free it yet */
- //gfxfontlist_free(fontlist, 1);
- gfxfontlist_free(fontlist, 0);
+ if(_fontlist)
+ gfxfontlist_free(_fontlist, 0);
}
-void gfxresult_record_replay(gfxresult_t*result, gfxdevice_t*device)
+void gfxresult_record_replay(gfxresult_t*result, gfxdevice_t*device, gfxfontlist_t**fontlist)
{
internal_result_t*i = (internal_result_t*)result->internal;
reader_init_memreader(&r, i->data, i->length);
}
- replay(0, device, &r);
+ replay(0, device, &r, fontlist);
}
static void record_result_write(gfxresult_t*r, int filedesc)
}
}
-void gfxdevice_record_flush(gfxdevice_t*dev, gfxdevice_t*out)
+void gfxdevice_record_flush(gfxdevice_t*dev, gfxdevice_t*out, gfxfontlist_t**fontlist)
{
internal_t*i = (internal_t*)dev->internal;
if(out) {
void*data = writer_growmemwrite_memptr(&i->w, &len);
reader_t r;
reader_init_memreader(&r, data, len);
- replay(dev, out, &r);
+ replay(dev, out, &r, fontlist);
writer_growmemwrite_reset(&i->w);
} else {
msg("<fatal> Flushing not supported for file based record device");
#define __record_h__
#include "../gfxdevice.h"
+#include "../gfxtools.h"
#ifdef __cplusplus
gfxdevice_t* gfxdevice_record_new(char*filename);
-void gfxdevice_record_flush(gfxdevice_t*, gfxdevice_t*);
+void gfxdevice_record_flush(gfxdevice_t*, gfxdevice_t*, gfxfontlist_t**);
-void gfxresult_record_replay(gfxresult_t*, gfxdevice_t*);
+void gfxresult_record_replay(gfxresult_t*, gfxdevice_t*, gfxfontlist_t**);
#ifdef __cplusplus
}
}
i->pass++;
- gfxresult_record_replay(r, dev);
+ gfxresult_record_replay(r, dev, 0);
r->destroy(r);
return twopass_finish(dev);
#include "../log.h"
#include "../png.h"
#include "../devices/record.h"
+#include "../gfxtools.h"
#include "../types.h"
#include "bbox.h"
this->gfxdev->setDevice(this->gfxoutput);
this->config_extrafontdata = 0;
+ this->config_optimizeplaincolorfills = 0;
this->bboxpath = 0;
//this->clipdev = 0;
//this->clipstates = 0;
void BitmapOutputDev::flushText()
{
msg("<verbose> Flushing text");
- gfxdevice_record_flush(this->gfxoutput, this->dev);
+
+ static gfxfontlist_t*output_font_list = 0;
+ static gfxdevice_t*last = 0;
+ if(last != this->dev) {
+ if(output_font_list)
+ gfxfontlist_free(output_font_list, 0);
+ output_font_list = gfxfontlist_create();
+ }
+ gfxdevice_record_flush(this->gfxoutput, this->dev, &output_font_list);
+ last = this->dev;
this->emptypage = 0;
}
rgbdev->stroke(state);
dbg_newdata("stroke");
}
+
+extern gfxcolor_t getFillColor(GfxState * state);
+
+char area_is_plain_colored(GfxState*state, SplashBitmap*boolpoly, SplashBitmap*rgbbitmap, int x1, int y1, int x2, int y2)
+{
+ int width = boolpoly->getWidth();
+ int height = boolpoly->getHeight();
+ if(!fixBBox(&x1, &y1, &x2, &y2, width, height)) {
+ return 0;
+ }
+ gfxcolor_t color = getFillColor(state);
+ SplashColorPtr rgb = rgbbitmap->getDataPtr()
+ + (y1*width+x1)*sizeof(SplashColor);
+ int width8 = (width+7)/8;
+ unsigned char*bits = (unsigned char*)boolpoly->getDataPtr()
+ + (y1*width8+x1);
+ int x,y;
+ int w = x2-x1;
+ int h = y2-y1;
+ for(y=0;y<h;y++) {
+ for(x=0;x<w;x++) {
+ if(rgb[x*3+0] != color.r ||
+ rgb[x*3+1] != color.g ||
+ rgb[x*3+2] != color.b)
+ return 0;
+ }
+ rgb += width*sizeof(SplashColor);
+ }
+ return 1;
+}
+
void BitmapOutputDev::fill(GfxState *state)
{
msg("<debug> fill");
boolpolydev->fill(state);
gfxbbox_t bbox = getBBox(state);
+ if(config_optimizeplaincolorfills) {
+ if(area_is_plain_colored(state, boolpolybitmap, rgbbitmap, bbox.xmin, bbox.ymin, bbox.xmax, bbox.ymax)) {
+ return;
+ }
+ }
checkNewBitmap(bbox.xmin, bbox.ymin, ceil(bbox.xmax), ceil(bbox.ymax));
rgbdev->fill(state);
dbg_newdata("fill");
virtual gfxbbox_t getBBox(GfxState*state);
char config_extrafontdata;
+ char config_optimizeplaincolorfills;
int layerstate;
GBool emptypage;
char*pfb;
int pfblen;
char*fullfilename;
+ DisplayFontParam *dfp;
} pdf2t1map[] ={
{"Times-Roman", "n021003l", n021003l_afm, n021003l_afm_len, n021003l_pfb, n021003l_pfb_len},
{"Times-Italic", "n021023l", n021023l_afm, n021023l_afm_len, n021023l_pfb, n021023l_pfb_len},
} else {
msg("<verbose> Storing standard PDF font %s at %s", name, pdf2t1map[t].fullfilename);
}
+ DisplayFontParam *dfp = new DisplayFontParam(new GString(fontName), displayFontT1);
+ dfp->t1.fileName = new GString(pdf2t1map[t].fullfilename);
+ pdf2t1map[t].dfp = dfp;
}
- DisplayFontParam *dfp = new DisplayFontParam(new GString(fontName), displayFontT1);
- dfp->t1.fileName = new GString(pdf2t1map[t].fullfilename);
- return dfp;
+ return pdf2t1map[t].dfp;
}
}
gfxdevice_t ops;
dbg("this->device=%p, this->device->name=%s\n", this->device, this->device->name);
gfxdevice_ops_init(&ops, this->device, alpha);
- gfxresult_record_replay(grouprecording, &ops);
+ gfxresult_record_replay(grouprecording, &ops, 0);
ops.finish(&ops);
}
grouprecording->destroy(grouprecording);
/* get outline of all objects below the soft mask */
gfxdevice_t uniondev;
gfxdevice_union_init(&uniondev, 0);
- gfxresult_record_replay(below, &uniondev);
+ gfxresult_record_replay(below, &uniondev, 0);
gfxline_t*belowoutline = gfxdevice_union_getunion(&uniondev);
uniondev.finish(&uniondev);
gfxbbox_t bbox = gfxline_getbbox(belowoutline);
gfxline_free(belowoutline);belowoutline=0;
#if 0
this->device->startclip(this->device, belowoutline);
- gfxresult_record_replay(below, this->device);
- gfxresult_record_replay(mask, this->device);
+ gfxresult_record_replay(below, this->device, 0);
+ gfxresult_record_replay(mask, this->device, 0);
this->device->endclip(this->device);
#endif
}
belowrender.setparameter(&belowrender, "antialize", "2");
belowrender.startpage(&belowrender, width, height);
- gfxresult_record_replay(below, &belowrender);
+ gfxresult_record_replay(below, &belowrender, 0);
belowrender.endpage(&belowrender);
gfxresult_t* belowresult = belowrender.finish(&belowrender);
gfximage_t* belowimg = (gfximage_t*)belowresult->get(belowresult,"page0");
gfxdevice_t maskrender;
gfxdevice_render_init(&maskrender);
maskrender.startpage(&maskrender, width, height);
- gfxresult_record_replay(mask, &maskrender);
+ gfxresult_record_replay(mask, &maskrender, 0);
maskrender.endpage(&maskrender);
gfxresult_t* maskresult = maskrender.finish(&maskrender);
gfximage_t* maskimg = (gfximage_t*)maskresult->get(maskresult,"page0");