#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
-#ifdef HAVE_FONTCONFIG_H
+#ifdef HAVE_FONTCONFIG
#include <fontconfig.h>
#endif
//xpdf header files
#include "swfoutput.h"
#include "../lib/log.h"
#include "../lib/gfxdevice.h"
-#include "gfxtools.h"
+#include "../lib/gfxtools.h"
+#include "../lib/gfxfont.h"
#include <math.h>
/* config */
static double caplinewidth = 3.0;
-static int zoom = 72; /* xpdf: 86 */
-static int forceType0Fonts = 0;
+static double zoom = 72; /* xpdf: 86 */
+static int forceType0Fonts = 1;
static void printInfoString(Dict *infoDict, char *key, char *fmt);
static void printInfoDate(Dict *infoDict, char *key, char *fmt);
{"Symbol", "s050000l"},
{"ZapfDingbats", "d050000l"}};
+class SWFOutputState {
+ public:
+ int clipping;
+ int textRender;
+ SWFOutputState() {
+ this->clipping = 0;
+ this->textRender = 0;
+ }
+};
+
+typedef struct _fontlist
+{
+ char*id;
+ char*filename;
+ gfxfont_t*font;
+ _fontlist*next;
+} fontlist_t;
+
class SWFOutputDev: public OutputDev {
int outputstarted;
struct swfoutput output;
//----- text drawing
virtual void beginString(GfxState *state, GString *s) ;
virtual void endString(GfxState *state) ;
+ virtual void endTextObject(GfxState *state);
virtual void drawChar(GfxState *state, double x, double y,
double dx, double dy,
double originX, double originY,
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, int *maskColors);
- int clipping[64];
- int clippos;
+ int SWFOutputDev::setGfxFont(char*id, char*filename);
+ void strokeGfxline(GfxState *state, gfxline_t*line);
+ void clipToGfxLine(GfxState *state, gfxline_t*line);
+ void fillGfxLine(GfxState *state, gfxline_t*line);
+
+ SWFOutputState states[64];
+ int statepos;
int currentpage;
int user_movex,user_movey;
int user_clipx1,user_clipx2,user_clipy1,user_clipy2;
+
+ gfxline_t* current_text_stroke;
+ gfxline_t* current_text_clip;
+ char* current_font_id;
+ gfxfont_t* current_gfxfont;
+ gfxmatrix_t current_font_matrix;
+
+ fontlist_t* fontlist;
};
static char*getFontID(GfxFont*font);
GfxFont*font = state->getFont();
if(!font)
return;
- char*id = getFontID(font);
+ /*char*id = getFontID(font);*/
/* FIXME*/
num_fonts++;
}
linkinfo = 0;
pbminfo = 0;
type3active = 0;
- clippos = 0;
- clipping[clippos] = 0;
+ statepos = 0;
outputstarted = 0;
xref = 0;
substitutepos = 0;
user_clipy1 = 0;
user_clipx2 = 0;
user_clipy2 = 0;
+ current_text_stroke = 0;
+ current_text_clip = 0;
+ fontlist = 0;
memset(&output, 0, sizeof(output));
// printf("SWFOutputDev::SWFOutputDev() \n");
};
static void dumpFontInfo(char*loglevel, GfxFont*font)
{
- char* name = getFontID(font);
+ char* id = getFontID(font);
+ char* name = getFontName(font);
Ref* r=font->getID();
- msg("%s=========== %s (ID:%d,%d) ==========\n", loglevel, getFontName(font), r->num,r->gen);
+ msg("%s=========== %s (ID:%d,%d) ==========\n", loglevel, name, r->num,r->gen);
GString*gstr = font->getTag();
- msg("%s| Tag: %s\n", loglevel, name);
+ msg("%s| Tag: %s\n", loglevel, id);
if(font->isCIDFont()) msg("%s| is CID font\n", loglevel);
Ref embRef;
GBool embedded = font->getEmbeddedFontID(&embRef);
- if(font->getEmbeddedFontName())
- name = font->getEmbeddedFontName()->getCString();
+ char*embeddedName=0;
+ if(font->getEmbeddedFontName()) {
+ embeddedName = font->getEmbeddedFontName()->getCString();
+ }
if(embedded)
- msg("%s| Embedded name: %s id: %d\n",loglevel, FIXNULL(name), embRef.num);
+ msg("%s| Embedded id: %s id: %d\n",loglevel, FIXNULL(embeddedName), embRef.num);
gstr = font->getExtFontFile();
if(gstr)
if(font->isSymbolic()) msg("%s| is symbolic\n", loglevel);
if(font->isItalic()) msg("%s| is italic\n", loglevel);
if(font->isBold()) msg("%s| is bold\n", loglevel);
+
+ free(id);
+ free(name);
}
//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");}
+
+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;
+ }
+}
+
gfxline_t* gfxPath_to_gfxline(GfxState*state, GfxPath*path, int closed)
{
int num = path->getNumSubpaths();
if(closed && needsfix && (fabs(posx-lastx)+fabs(posy-lasty))>0.001) {
draw.lineTo(&draw, lastx, lasty);
}
- return (gfxline_t*)draw.result(&draw);
-}
-
-
-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;
- }
+ gfxline_t*result = (gfxline_t*)draw.result(&draw);
+ return result;
}
/*----------------------------------------------------------------------------
void SWFOutputDev::stroke(GfxState *state)
{
GfxPath * path = state->getPath();
+ gfxline_t*line= gfxPath_to_gfxline(state, path, 0);
+ strokeGfxline(state, line);
+ gfxline_free(line);
+}
+
+void SWFOutputDev::strokeGfxline(GfxState *state, gfxline_t*line)
+{
int lineCap = state->getLineCap(); // 0=butt, 1=round 2=square
int lineJoin = state->getLineJoin(); // 0=miter, 1=round 2=bevel
double miterLimit = state->getMiterLimit();
GfxRGB rgb;
double opaq = state->getStrokeOpacity();
- state->getStrokeRGB(&rgb);
+ 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(lineJoin == 1) joinType = gfx_joinRound;
else if(lineJoin == 2) joinType = gfx_joinBevel;
- gfxline_t*line= gfxPath_to_gfxline(state, path, 0);
-
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));
int t;
dump_outline(line);
}
- gfxline_t*line2 = gfxtool_dash_line(line, dash, dashphase);
- gfxline_free(line);
+ line2 = gfxtool_dash_line(line, dash, dashphase);
line = line2;
msg("<trace> After dashing:");
}
if(getLogLevel() >= LOGLEVEL_TRACE) {
- msg("<trace> stroke width=%f join=%s cap=%s dashes=%d\n",
+ 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
+ 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);
+
+ if(line2)
+ gfxline_free(line2);
}
-void SWFOutputDev::fill(GfxState *state)
+
+gfxcolor_t getFillColor(GfxState * state)
{
- GfxPath * path = state->getPath();
- double opaq = state->getFillOpacity();
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);
+ return col;
+}
- gfxline_t*line= gfxPath_to_gfxline(state, path, 1);
+void SWFOutputDev::fillGfxLine(GfxState *state, gfxline_t*line)
+{
+ gfxcolor_t col = getFillColor(state);
if(getLogLevel() >= LOGLEVEL_TRACE) {
msg("<trace> fill %02x%02x%02x%02x\n", col.r, col.g, col.b, col.a);
dump_outline(line);
}
-
swfoutput_fillgfxline(&output, line, &col);
+}
+void SWFOutputDev::fill(GfxState *state)
+{
+ GfxPath * path = state->getPath();
+ gfxline_t*line= gfxPath_to_gfxline(state, path, 1);
+ fillGfxLine(state, line);
gfxline_free(line);
}
void SWFOutputDev::eoFill(GfxState *state)
{
GfxPath * path = state->getPath();
- 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);
+ gfxcolor_t col = getFillColor(state);
gfxline_t*line= gfxPath_to_gfxline(state, path, 1);
swfoutput_fillgfxline(&output, line, &col);
gfxline_free(line);
}
+
void SWFOutputDev::clip(GfxState *state)
{
GfxPath * path = state->getPath();
gfxline_t*line = gfxPath_to_gfxline(state, path, 1);
+ clipToGfxLine(state, line);
+ gfxline_free(line);
+}
+void SWFOutputDev::clipToGfxLine(GfxState *state, gfxline_t*line)
+{
if(getLogLevel() >= LOGLEVEL_TRACE) {
msg("<trace> clip\n");
dump_outline(line);
}
swfoutput_startclip(&output, line);
- clipping[clippos] ++;
- gfxline_free(line);
+ states[statepos].clipping++;
}
void SWFOutputDev::eoClip(GfxState *state)
{
}
swfoutput_startclip(&output, line);
- clipping[clippos] ++;
+ states[statepos].clipping++;
gfxline_free(line);
}
{
swfoutput_destroy(&output);
outputstarted = 0;
+
+ fontlist_t*l = this->fontlist;
+ while(l) {
+ fontlist_t*next = l->next;
+ l->next = 0;
+ gfxfont_free(l->font);
+ free(l->id);
+ free(l->filename);
+ free(l);
+ l = next;
+ }
};
GBool SWFOutputDev::upsideDown()
{
return gTrue;
}
+char*renderModeDesc[]= {"fill", "stroke", "fill+stroke", "invisible",
+ "clip+fill", "stroke+clip", "fill+stroke+clip", "clip"};
+
+#define RENDER_FILL 0
+#define RENDER_STROKE 1
+#define RENDER_FILLSTROKE 2
+#define RENDER_INVISIBLE 3
+#define RENDER_CLIP 4
+
+static char tmp_printstr[4096];
+char* makeStringPrintable(char*str)
+{
+ int len = strlen(str);
+ int dots = 0;
+ if(len>=80) {
+ len = 80;
+ dots = 1;
+ }
+ int t;
+ for(t=0;t<len;t++) {
+ char c = str[t];
+ if(c<32 || c>124) {
+ c = '.';
+ }
+ tmp_printstr[t] = c;
+ }
+ if(dots) {
+ tmp_printstr[len++] = '.';
+ tmp_printstr[len++] = '.';
+ tmp_printstr[len++] = '.';
+ }
+ tmp_printstr[len] = 0;
+ return tmp_printstr;
+}
+
+
+int getGfxCharID(gfxfont_t*font, int charnr, char *charname, int u)
+{
+ int t;
+ if(charname) {
+ for(t=0;t<font->num_glyphs;t++) {
+ if(font->glyphs[t].name && !strcmp(font->glyphs[t].name,charname)) {
+ msg("<debug> Char [%d,>%s<,%d] maps to %d\n", charnr, charname, u, t);
+ return t;
+ }
+ }
+ /* if we didn't find the character, maybe
+ we can find the capitalized version */
+ for(t=0;t<font->num_glyphs;t++) {
+ if(font->glyphs[t].name && !strcasecmp(font->glyphs[t].name,charname)) {
+ msg("<debug> Char [%d,>>%s<<,%d] maps to %d\n", charnr, charname, u, t);
+ return t;
+ }
+ }
+ }
+
+ /* try to use the unicode id */
+ if(u>=0 && u<font->max_unicode && font->unicode2glyph[u]>=0) {
+ msg("<debug> Char [%d,%s,>%d<] maps to %d\n", charnr, charname, u, font->unicode2glyph[u]);
+ return font->unicode2glyph[u];
+ }
+
+ if(charnr>=0 && charnr<font->num_glyphs) {
+ msg("<debug> Char [>%d<,%s,%d] maps to %d\n", charnr, charname, u, charnr);
+ return charnr;
+ }
+
+ return -1;
+}
+
+
void SWFOutputDev::beginString(GfxState *state, GString *s)
{
+ int render = state->getRender();
+ if(current_text_stroke) {
+ msg("<error> Error: Incompatible change of text rendering to %d while inside cliptext", render);
+ }
+
+ msg("<trace> beginString(%s) render=%d", makeStringPrintable(s->getCString()), render);
double m11,m21,m12,m22;
// msg("<debug> %s beginstring \"%s\"\n", gfxstate2str(state), s->getCString());
state->getFontTransMat(&m11, &m12, &m21, &m22);
m11 *= state->getHorizScaling();
m21 *= state->getHorizScaling();
- swfoutput_setfontmatrix(&output, m11, -m21, m12, -m22);
+
+ this->current_font_matrix.m00 = m11 / 1024.0;
+ this->current_font_matrix.m01 = m12 / 1024.0;
+ this->current_font_matrix.m10 = -m21 / 1024.0;
+ this->current_font_matrix.m11 = -m22 / 1024.0;
+ this->current_font_matrix.tx = 0;
+ this->current_font_matrix.ty = 0;
+
+ gfxmatrix_t m = this->current_font_matrix;
+
+ /*if(render != 3 && render != 0)
+ msg("<warning> Text rendering mode %d (%s) not fully supported yet (for text \"%s\")", render, renderModeDesc[render&7], makeStringPrintable(s->getCString()));*/
+ states[statepos].textRender = render;
}
void SWFOutputDev::drawChar(GfxState *state, double x, double y,
double originX, double originY,
CharCode c, Unicode *_u, int uLen)
{
+ int render = state->getRender();
// check for invisible text -- this is used by Acrobat Capture
- if ((state->getRender() & 3) == 3)
+ if (render == 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);
+
+ if(states[statepos].textRender != render)
+ msg("<error> Internal error: drawChar.render!=beginString.render");
+
+ gfxcolor_t col = getFillColor(state);
Gushort *CIDToGIDMap = 0;
GfxFont*font = state->getFont();
if(font->getType() == fontType3) {
/* type 3 chars are passed as graphics */
+ msg("<debug> type3 char at %f/%f", x, y);
return;
}
- double x1,y1;
- x1 = x;
- y1 = y;
- state->transform(x, y, &x1, &y1);
Unicode u=0;
char*name=0;
if(font->isCIDFont()) {
GfxCIDFont*cfont = (GfxCIDFont*)font;
- if(font->getType() == fontCIDType2) {
+ if(font->getType() == fontCIDType2)
CIDToGIDMap = cfont->getCIDToGID();
- }
} else {
Gfx8BitFont*font8;
font8 = (Gfx8BitFont*)font;
if(enc && enc[c])
name = enc[c];
}
-
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, &col);
+ msg("<debug> drawChar(%f, %f, c='%c' (%d), GID=%d, u=%d <%d>) CID=%d name=\"%s\" render=%d\n", x, y, (c&127)>=32?c:'?', c, CIDToGIDMap[c], u, uLen, font->isCIDFont(), FIXNULL(name), render);
+ c = CIDToGIDMap[c];
+ } else {
+ msg("<debug> drawChar(%f,%f,c='%c' (%d), u=%d <%d>) CID=%d name=\"%s\" render=%d\n",x,y,(c&127)>=32?c:'?',c,u, uLen, font->isCIDFont(), FIXNULL(name), render);
+ }
+
+ int charid = getGfxCharID(current_gfxfont, c, name, u);
+ if(charid<0) {
+ msg("<warning> Didn't find character '%s' (c=%d,u=%d) in current charset (%s, %d characters)",
+ FIXNULL(name),c, u, FIXNULL((char*)current_font_id), current_gfxfont->num_glyphs);
+ return;
+ }
+
+ gfxmatrix_t m = this->current_font_matrix;
+ state->transform(x, y, &m.tx, &m.ty);
+
+ if(render == RENDER_FILL) {
+ swfoutput_gfxdrawchar(&output, current_font_id, charid, &col, &m);
} 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, &col);
+ msg("<debug> Drawing glyph %d as shape", charid);
+ gfxline_t*glyph = current_gfxfont->glyphs[charid].line;
+ gfxline_t*tglyph = gfxline_clone(glyph);
+ gfxline_transform(tglyph, &m);
+ if((render&3) != RENDER_INVISIBLE) {
+ gfxline_t*add = gfxline_clone(tglyph);
+ current_text_stroke = gfxline_append(current_text_stroke, add);
+ }
+ if(render&RENDER_CLIP) {
+ gfxline_t*add = gfxline_clone(tglyph);
+ current_text_clip = gfxline_append(current_text_clip, add);
+ }
+ gfxline_free(tglyph);
}
}
-void SWFOutputDev::endString(GfxState *state) {
+void SWFOutputDev::endString(GfxState *state)
+{
+ int render = state->getRender();
+ msg("<trace> endString() render=%d textstroke=%08x", render, current_text_stroke);
+ if(states[statepos].textRender != render)
+ msg("<error> Internal error: drawChar.render!=beginString.render");
+
+ if(current_text_stroke) {
+ /* fillstroke and stroke text rendering objects we can process right
+ now (as there may be texts of other rendering modes in this
+ text object)- clipping objects have to wait until endTextObject,
+ however */
+ if((render&3) == RENDER_FILL) {
+ fillGfxLine(state, current_text_stroke);
+ gfxline_free(current_text_stroke);
+ current_text_stroke = 0;
+ } else if((render&3) == RENDER_FILLSTROKE) {
+ fillGfxLine(state, current_text_stroke);
+ strokeGfxline(state, current_text_stroke);
+ gfxline_free(current_text_stroke);
+ current_text_stroke = 0;
+ } else if((render&3) == RENDER_STROKE) {
+ strokeGfxline(state, current_text_stroke);
+ gfxline_free(current_text_stroke);
+ current_text_stroke = 0;
+ }
+ }
}
-
-GBool SWFOutputDev::beginType3Char(GfxState *state,
- CharCode code, Unicode *u, int uLen)
+void SWFOutputDev::endTextObject(GfxState *state)
+{
+ int render = state->getRender();
+ msg("<trace> endTextObject() render=%d textstroke=%08x clipstroke=%08x", render, current_text_stroke, current_text_clip);
+ if(states[statepos].textRender != render)
+ msg("<error> Internal error: drawChar.render!=beginString.render");
+
+ if(current_text_clip) {
+ clipToGfxLine(state, current_text_clip);
+ gfxline_free(current_text_clip);
+ current_text_clip = 0;
+ }
+}
+
+/* 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::saveState(GfxState *state) {
- msg("<debug> saveState\n");
+ msg("<trace> saveState\n");
updateAll(state);
- if(clippos<64)
- clippos ++;
- else
+ if(statepos>=64) {
msg("<error> Too many nested states in pdf.");
- clipping[clippos] = 0;
+ return;
+ }
+ statepos ++;
+ states[statepos].clipping = 0; //? shouldn't this be the current value?
+ states[statepos].textRender = states[statepos-1].textRender;
};
void SWFOutputDev::restoreState(GfxState *state) {
- msg("<debug> restoreState\n");
+ msg("<trace> restoreState\n");
updateAll(state);
- while(clipping[clippos]) {
+ while(states[statepos].clipping) {
swfoutput_endclip(&output);
- clipping[clippos]--;
+ states[statepos].clipping--;
}
- clippos--;
+ statepos--;
}
char* SWFOutputDev::searchFont(char*name)
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));
}
msg("<notice> Collection: %s", c.getCString());
}*/
- if (font->getType() == fontType1C ||
- font->getType() == fontCIDType0C) {
+ //if (font->getType() == fontType1C) {
+ if (0) { //font->getType() == fontType1C) {
if (!(fontBuf = font->readEmbFontFile(xref, &fontLen))) {
fclose(f);
msg("<error> Couldn't read embedded font file");
if (!fcinitcalled) {
msg("<debug> Initializing FontConfig...");
fcinitcalled = true;
- if(FcInit()) {
+ if(!FcInit()) {
msg("<debug> FontConfig Initialization failed. Disabling.");
config_use_fontconfig = 0;
return 0;
// if we get an exact match
if (strcmp((char *)v, name) == 0) {
if (FcPatternGetString(match, "file", 0, &v) == FcResultMatch) {
- filename = strdup((char*)v);
+ filename = strdup((char*)v); // mem leak
char *nfn = strrchr(filename, '/');
if(nfn) fontname = strdup(nfn+1);
else fontname = filename;
match = FcFontMatch (0, pattern, &result);
if (FcPatternGetString(match, "file", 0, &v) == FcResultMatch) {
- filename = strdup((char*)v);
+ filename = strdup((char*)v); // mem leak
char *nfn = strrchr(filename, '/');
if(nfn) fontname = strdup(nfn+1);
else fontname = filename;
}
filename = searchFont(fontname);
if(!filename) {
- msg("<error> Couldn't find font %s- did you install the default fonts?");
+ msg("<error> Couldn't find font %s- did you install the default fonts?", fontname);
return 0;
}
exit(1);
}
if(oldname) {
- substitutesource[substitutepos] = oldname;
+ substitutesource[substitutepos] = strdup(oldname); //mem leak
substitutetarget[substitutepos] = fontname;
msg("<notice> substituting %s -> %s", FIXNULL(oldname), FIXNULL(fontname));
substitutepos ++;
}
- return strdup(filename);
+ return strdup(filename); //mem leak
}
void unlinkfont(char* filename)
this->xref = xref;
}
+int SWFOutputDev::setGfxFont(char*id, char*filename)
+{
+ gfxfont_t*font = 0;
+ fontlist_t*last=0,*l = this->fontlist;
+
+ /* TODO: should this be part of the state? */
+ while(l) {
+ last = l;
+ if(!strcmp(l->id, id)) {
+ current_font_id = l->id;
+ current_gfxfont = l->font;
+ font = l->font;
+ swfoutput_gfxaddfont(&this->output, id, current_gfxfont);
+ return 1;
+ }
+ l = l->next;
+ }
+ if(!filename) return 0;
+ font = gfxfont_load(filename);
+ l = new fontlist_t;
+ l->font = font;
+ l->filename = strdup(filename);
+ l->id = strdup(id);
+ l->next = 0;
+ current_font_id = l->id;
+ current_gfxfont = l->font;
+ if(last) {
+ last->next = l;
+ } else {
+ this->fontlist = l;
+ }
+ swfoutput_gfxaddfont(&this->output, id, current_gfxfont);
+ return 1;
+}
void SWFOutputDev::updateFont(GfxState *state)
{
too often */
for(t=0;t<substitutepos;t++) {
if(!strcmp(fontid, substitutesource[t])) {
- fontid = substitutetarget[t];
+ free(fontid);fontid=0;
+ fontid = strdup(substitutetarget[t]);
break;
}
}
- /* second, see if swfoutput already has this font
- cached- if so, we are done */
- if(swfoutput_queryfont(&output, fontid))
- {
+ /* second, see if this is a font which was used before-
+ if so, we are done */
+ if(setGfxFont(fontid, 0)) {
+ free(fontid);
+ return;
+ }
+/* if(swfoutput_queryfont(&output, fontid))
swfoutput_setfont(&output, fontid, 0);
msg("<debug> updateFont(%s) [cached]", fontid);
return;
- }
+ }*/
// look for Type 3 font
if (gfxFont->getType() == fontType3) {
type3Warning = gTrue;
showFontError(gfxFont, 2);
}
+ free(fontid);
return;
}
msg("<warning> Font %s %scould not be loaded.", fontname, embedded?"":"(not embedded) ");
msg("<warning> Try putting a TTF version of that font (named \"%s.ttf\") into /swftools/fonts", fontname);
fileName = substituteFont(gfxFont, fontid);
- if(fontid) { fontid = substitutetarget[substitutepos-1]; /*ugly hack*/};
+ if(fontid) { free(fontid);fontid = strdup(substitutetarget[substitutepos-1]); /*ugly hack*/};
msg("<notice> Font is now %s (%s)", fontid, fileName);
}
if(!fileName) {
msg("<error> Couldn't set font %s\n", fontid);
+ free(fontid);
return;
}
msg("<verbose> updateFont(%s) -> %s", fontid, fileName);
dumpFontInfo("<verbose>", gfxFont);
- swfoutput_setfont(&output, fontid, fileName);
+ //swfoutput_setfont(&output, fontid, fileName);
+
+ if(!setGfxFont(fontid, 0)) {
+ setGfxFont(fontid, fileName);
+ }
if(fileName && del)
unlinkfont(fileName);
if(fileName)
free(fileName);
+ free(fontid);
}
#define SQR(x) ((x)*(x))
int width, int height, GBool invert,
GBool inlineImg)
{
+ if(states[statepos].textRender & 4) //clipped
+ return;
msg("<verbose> drawImageMask %dx%d, invert=%d inline=%d", width, height, invert, inlineImg);
drawGeneralImage(state,ref,str,width,height,0,invert,inlineImg,1, 0);
}
int width, int height, GfxImageColorMap *colorMap,
int *maskColors, GBool inlineImg)
{
+ if(states[statepos].textRender & 4) //clipped
+ return;
+
msg("<verbose> drawImage %dx%d, %s %s, inline=%d", width, height,
colorMap?"colorMap":"no colorMap",
maskColors?"maskColors":"no maskColors",
caplinewidth = atof(value);
} else if(!strcmp(name, "zoom")) {
char buf[80];
- zoom = atoi(value);
+ zoom = atof(value);
sprintf(buf, "%f", (double)jpeg_dpi/(double)zoom);
swfoutput_setparameter("jpegsubpixels", buf);
sprintf(buf, "%f", (double)ppm_dpi/(double)zoom);