#include <string.h>
#include <unistd.h>
#include "../config.h"
+#ifdef HAVE_FONTCONFIG_H
+#include <fontconfig.h>
+#endif
//xpdf header files
#include "config.h"
#include "gfile.h"
#include "GfxFont.h"
#include "CharCodeToUnicode.h"
#include "NameToUnicodeTable.h"
-#include "FontFile.h"
#include "GlobalParams.h"
+//#define XPDF_101
+#ifdef XPDF_101
+#include "FontFile.h"
+#else
+#include "FoFiType1C.h"
+#include "FoFiTrueType.h"
+#endif
+#include "SWFOutputDev.h"
+
//swftools header files
#include "swfoutput.h"
#include "../lib/log.h"
static int numpages;
static int currentpage;
-static char*fonts[2048];
+typedef struct _fontfile
+{
+ char*filename;
+ int used;
+} fontfile_t;
+
+static fontfile_t fonts[2048];
static int fontnum = 0;
// swf <-> pdf pages
static int pagepos = 0;
static double caplinewidth = 3.0;
+static int zoom = 72; /* xpdf: 86 */
static void printInfoString(Dict *infoDict, char *key, char *fmt);
static void printInfoDate(Dict *infoDict, char *key, char *fmt);
-static double fontsizes[] =
-{
- 0.833,0.833,0.889,0.889,
- 0.788,0.722,0.833,0.778,
- 0.600,0.600,0.600,0.600,
- 0.576,0.576,0.576,0.576,
- 0.733 //?
-};
-static char*fontnames[]={
-"Helvetica",
-"Helvetica-Bold",
-"Helvetica-BoldOblique",
-"Helvetica-Oblique",
-"Times-Roman",
-"Times-Bold",
-"Times-BoldItalic",
-"Times-Italic",
-"Courier",
-"Courier-Bold",
-"Courier-BoldOblique",
-"Courier-Oblique",
-"Symbol",
-"Symbol",
-"Symbol",
-"Symbol",
-"ZapfDingBats"
-};
-
struct mapping {
char*pdffont;
char*filename;
- int id;
} pdf2t1map[] ={
{"Times-Roman", "n021003l"},
{"Times-Italic", "n021023l"},
{"Symbol", "s050000l"},
{"ZapfDingbats", "d050000l"}};
-class GfxState;
-class GfxImageColorMap;
-
class SWFOutputDev: public OutputDev {
struct swfoutput output;
int outputstarted;
// Does this device use drawChar() or drawString()?
virtual GBool useDrawChar();
+ // Can this device draw gradients?
+ virtual GBool useGradients();
+
virtual GBool interpretType3Chars() {return gTrue;}
//----- initialization and control
int pbminfo; // did we write "File contains jpegs" yet?
int linkinfo; // did we write "File contains links" yet?
int ttfinfo; // did we write "File contains TrueType Fonts" yet?
+ int gradientinfo; // did we write "File contains Gradients yet?
int type3active; // are we between beginType3()/endType3()?
GfxState *laststate;
+
+ int pic_xids[1024];
+ int pic_yids[1024];
+ int pic_ids[1024];
+ int pic_width[1024];
+ int pic_height[1024];
+ int picpos;
+ int pic_id;
+ char type3Warning;
+
+ char* substitutetarget[256];
+ char* substitutesource[256];
+ int substitutepos;
};
-char*getFontName(GfxFont*font)
+SWFOutputDev::SWFOutputDev()
+{
+ jpeginfo = 0;
+ ttfinfo = 0;
+ linkinfo = 0;
+ pbminfo = 0;
+ type3active = 0;
+ clippos = 0;
+ clipping[clippos] = 0;
+ outputstarted = 0;
+ xref = 0;
+ picpos = 0;
+ pic_id = 0;
+ substitutepos = 0;
+ type3Warning = 0;
+// printf("SWFOutputDev::SWFOutputDev() \n");
+};
+
+static char*getFontID(GfxFont*font)
{
GString*gstr = font->getName();
char* fontname = gstr==0?0:gstr->getCString();
sprintf(buf, "UFONT%d", r->num);
return strdup(buf);
}
+ return fontname;
+}
+
+static char*getFontName(GfxFont*font)
+{
+ char*fontname = getFontID(font);
char* plus = strchr(fontname, '+');
if(plus && plus < &fontname[strlen(fontname)-1])
fontname = plus+1;
return fontname;
}
-char mybuf[1024];
-char* gfxstate2str(GfxState *state)
+static char mybuf[1024];
+static char* gfxstate2str(GfxState *state)
{
char*bufpos = mybuf;
GfxRGB rgb;
if(state->getLineJoin()!=0)
bufpos+=sprintf(bufpos,"ML%d ", state->getMiterLimit());
- if(state->getFont() && getFontName(state->getFont()))
- bufpos+=sprintf(bufpos,"F\"%s\" ",getFontName(state->getFont()));
+ if(state->getFont() && getFontID(state->getFont()))
+ bufpos+=sprintf(bufpos,"F\"%s\" ",getFontID(state->getFont()));
bufpos+=sprintf(bufpos,"FS%.1f ", state->getFontSize());
bufpos+=sprintf(bufpos,"MAT[%.1f/%.1f/%.1f/%.1f/%.1f/%.1f] ", state->getTextMat()[0],state->getTextMat()[1],state->getTextMat()[2],
state->getTextMat()[3],state->getTextMat()[4],state->getTextMat()[5]);
return mybuf;
}
-
-
-void dumpFontInfo(char*loglevel, GfxFont*font);
-int lastdumps[1024];
-int lastdumppos = 0;
+static void dumpFontInfo(char*loglevel, GfxFont*font);
+static int lastdumps[1024];
+static int lastdumppos = 0;
/* nr = 0 unknown
nr = 1 substituting
nr = 2 type 3
*/
-void showFontError(GfxFont*font, int nr)
+static void showFontError(GfxFont*font, int nr)
{
Ref*r=font->getID();
int t;
dumpFontInfo("<warning>", font);
}
-void dumpFontInfo(char*loglevel, GfxFont*font)
+static void dumpFontInfo(char*loglevel, GfxFont*font)
{
- char* name = getFontName(font);
+ char* name = getFontID(font);
Ref* r=font->getID();
- msg("%s=========== %s (ID:%d,%d) ==========\n", loglevel, name, r->num,r->gen);
+ msg("%s=========== %s (ID:%d,%d) ==========\n", loglevel, getFontName(font), r->num,r->gen);
GString*gstr = font->getTag();
- msg("%sTag: %s\n", loglevel, name);
+ msg("%s| Tag: %s\n", loglevel, name);
- if(font->isCIDFont()) msg("%sis CID font\n", loglevel);
+ if(font->isCIDFont()) msg("%s| is CID font\n", loglevel);
GfxFontType type=font->getType();
switch(type) {
case fontUnknownType:
- msg("%sType: unknown\n",loglevel);
+ msg("%s| Type: unknown\n",loglevel);
break;
case fontType1:
- msg("%sType: 1\n",loglevel);
+ msg("%s| Type: 1\n",loglevel);
break;
case fontType1C:
- msg("%sType: 1C\n",loglevel);
+ msg("%s| Type: 1C\n",loglevel);
break;
case fontType3:
- msg("%sType: 3\n",loglevel);
+ msg("%s| Type: 3\n",loglevel);
break;
case fontTrueType:
- msg("%sType: TrueType\n",loglevel);
+ msg("%s| Type: TrueType\n",loglevel);
break;
case fontCIDType0:
- msg("%sType: CIDType0\n",loglevel);
+ msg("%s| Type: CIDType0\n",loglevel);
break;
case fontCIDType0C:
- msg("%sType: CIDType0C\n",loglevel);
+ msg("%s| Type: CIDType0C\n",loglevel);
break;
case fontCIDType2:
- msg("%sType: CIDType2\n",loglevel);
+ msg("%s| Type: CIDType2\n",loglevel);
break;
}
if(font->getEmbeddedFontName())
name = font->getEmbeddedFontName()->getCString();
if(embedded)
- msg("%sEmbedded name: %s id: %d\n",loglevel, FIXNULL(name), embRef.num);
+ msg("%s| Embedded name: %s id: %d\n",loglevel, FIXNULL(name), embRef.num);
gstr = font->getExtFontFile();
if(gstr)
- msg("%sExternal Font file: %s\n", loglevel, FIXNULL(gstr->getCString()));
+ msg("%s| External Font file: %s\n", loglevel, FIXNULL(gstr->getCString()));
// Get font descriptor flags.
- if(font->isFixedWidth()) msg("%sis fixed width\n", loglevel);
- if(font->isSerif()) msg("%sis serif\n", loglevel);
- if(font->isSymbolic()) msg("%sis symbolic\n", loglevel);
- if(font->isItalic()) msg("%sis italic\n", loglevel);
- if(font->isBold()) msg("%sis bold\n", loglevel);
+ if(font->isFixedWidth()) msg("%s| is fixed width\n", loglevel);
+ if(font->isSerif()) msg("%s| is serif\n", loglevel);
+ 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);
}
//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");}
-SWFOutputDev::SWFOutputDev()
+static void free_outline(SWF_OUTLINE*outline)
{
- jpeginfo = 0;
- ttfinfo = 0;
- linkinfo = 0;
- pbminfo = 0;
- type3active = 0;
- clippos = 0;
- clipping[clippos] = 0;
- outputstarted = 0;
- xref = 0;
-// printf("SWFOutputDev::SWFOutputDev() \n");
-};
+ while(outline) {
+ SWF_OUTLINE*next = outline->link;
+ free(outline);
+ outline = next;
+ }
+}
SWF_OUTLINE* gfxPath_to_SWF_OUTLINE(GfxState*state, GfxPath*path)
{
updateStrokeColor(state); //reset
updateFillColor(state); //reset
}
+ free_outline(outline);
}
void SWFOutputDev::fill(GfxState *state)
{
SWFOutputDev::~SWFOutputDev()
{
+ swfoutput_save(&output, swffilename);
swfoutput_destroy(&output);
outputstarted = 0;
};
GBool SWFOutputDev::upsideDown()
{
- msg("<debug> upsidedown?");
+ msg("<debug> upsidedown? yes");
return gTrue;
};
GBool SWFOutputDev::useDrawChar()
{
- msg("<debug> usedrawchar?");
+ return gTrue;
+}
+GBool SWFOutputDev::useGradients()
+{
+ if(!gradientinfo)
+ {
+ msg("<notice> File contains gradients");
+ gradientinfo = 1;
+ }
return gTrue;
}
swfoutput_setfontmatrix(&output, m11, -m21, m12, -m22);
}
-int charcounter = 0;
void SWFOutputDev::drawChar(GfxState *state, double x, double y,
double dx, double dy,
double originX, double originY,
GfxFont*font = state->getFont();
if(font->getType() == fontType3) {
- /* type 3 chars are passed primarily as graphics */
+ /* type 3 chars are passed as graphics */
return;
}
double x1,y1;
x1 = x;
y1 = y;
state->transform(x, y, &x1, &y1);
-
+
Unicode u=0;
- if(_u)
+ if(_u && uLen)
u = *_u;
-
- msg("<debug> drawChar(%f,%f,%f,%f,c='%c' (%d),u=%d) CID=%d\n",x,y,dx,dy,c,c,u, font->isCIDFont());
- if(font->isCIDFont()) {
+ /* find out the character name */
+ char*name=0;
+ if(font->isCIDFont() && u) {
GfxCIDFont*cfont = (GfxCIDFont*)font;
- char*name=0;
- if(u) {
- int t;
- for(t=0;t<sizeof(nameToUnicodeTab)/sizeof(nameToUnicodeTab[0]);t++)
- /* todo: should be precomputed */
- if(nameToUnicodeTab[t].u == u) {
- name = nameToUnicodeTab[t].name;
- break;
- }
- }
-
- if(name)
- swfoutput_drawchar(&output, x1, y1, name, c, u);
- else {
- swfoutput_drawchar(&output, x1, y1, 0, c, u);
+ int t;
+ for(t=0;t<sizeof(nameToUnicodeTab)/sizeof(nameToUnicodeTab[0]);t++) {
+ /* todo: should be precomputed */
+ if(nameToUnicodeTab[t].u == u) {
+ name = nameToUnicodeTab[t].name;
+ break;
+ }
}
} else {
Gfx8BitFont*font8;
font8 = (Gfx8BitFont*)font;
char**enc=font8->getEncoding();
-
if(enc && enc[c])
- swfoutput_drawchar(&output, x1, y1, enc[c], c, u);
- else {
- swfoutput_drawchar(&output, x1, y1, 0, c, u);
- }
+ name = enc[c];
}
+
+ 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));
+
+ /*x1 = (int)(x1+0.5);
+ y1 = (int)(y1+0.5);*/
+
+ int ret = swfoutput_drawchar(&output, x1, y1, name, c, u);
}
-void SWFOutputDev::endString(GfxState *state)
-{
- msg("<debug> endstring\n");
+void SWFOutputDev::endString(GfxState *state) {
}
void SWFOutputDev::startPage(int pageNum, GfxState *state, double crop_x1, double crop_y1, double crop_x2, double crop_y2)
{
double x1,y1,x2,y2;
+ int rot = doc->getPageRotate(1);
laststate = state;
msg("<verbose> startPage %d (%f,%f,%f,%f)\n", pageNum, crop_x1, crop_y1, crop_x2, crop_y2);
- msg("<notice> processing page %d", pageNum);
+ if(rot!=0)
+ msg("<verbose> page is rotated %d degrees\n", rot);
/* state->transform(state->getX1(),state->getY1(),&x1,&y1);
state->transform(state->getX2(),state->getY2(),&x2,&y2);
Use CropBox, not MediaBox, as page size
*/
- x1 = crop_x1;
+
+ /*x1 = crop_x1;
y1 = crop_y1;
x2 = crop_x2;
- y2 = crop_y2;
+ y2 = crop_y2;*/
+ state->transform(crop_x1,crop_y1,&x1,&y1);
+ state->transform(crop_x2,crop_y2,&x2,&y2);
if(x2<x1) {double x3=x1;x1=x2;x2=x3;}
if(y2<y1) {double y3=y1;y1=y2;y2=y3;}
if(!outputstarted) {
msg("<verbose> Bounding box is (%f,%f)-(%f,%f)", x1,y1,x2,y2);
- swfoutput_init(&output, swffilename,(int)x1,(int)y1,(int)x2,(int)y2);
+ swfoutput_init(&output);
outputstarted = 1;
}
- else
- swfoutput_newpage(&output);
+
+ swfoutput_newpage(&output, pageNum, (int)x1, (int)y1, (int)x2, (int)y2);
}
void SWFOutputDev::drawLink(Link *link, Catalog *catalog)
{
- msg("<debug> drawlink\n");
- double x1, y1, x2, y2, w;
- GfxRGB rgb;
- swfcoord points[5];
- int x, y;
-
- link->getBorder(&x1, &y1, &x2, &y2, &w);
-// if (w > 0)
- {
+ msg("<debug> drawlink\n");
+ double x1, y1, x2, y2, w;
+ GfxRGB rgb;
+ swfcoord points[5];
+ int x, y;
+
+#ifdef XPDF_101
+ link->getBorder(&x1, &y1, &x2, &y2, &w);
+#else
+ link->getRect(&x1, &y1, &x2, &y2);
+#endif
rgb.r = 0;
rgb.g = 0;
rgb.b = 1;
LinkAction*action=link->getAction();
char buf[128];
- char*s = "-?-";
+ char*s = 0;
char*type = "-?-";
char*url = 0;
char*named = 0;
int page = -1;
switch(action->getKind())
{
- case actionGoTo: {
- type = "GoTo";
- LinkGoTo *ha=(LinkGoTo *)link->getAction();
- LinkDest *dest=NULL;
- if (ha->getDest()==NULL)
- dest=catalog->findDest(ha->getNamedDest());
- else dest=ha->getDest();
- if (dest){
- if (dest->isPageRef()){
- Ref pageref=dest->getPageRef();
- page=catalog->findPage(pageref.num,pageref.gen);
- }
- else page=dest->getPageNum();
- sprintf(buf, "%d", page);
- s = buf;
- }
- }
+ case actionGoTo: {
+ type = "GoTo";
+ LinkGoTo *ha=(LinkGoTo *)link->getAction();
+ LinkDest *dest=NULL;
+ if (ha->getDest()==NULL)
+ dest=catalog->findDest(ha->getNamedDest());
+ else dest=ha->getDest();
+ if (dest){
+ if (dest->isPageRef()){
+ Ref pageref=dest->getPageRef();
+ page=catalog->findPage(pageref.num,pageref.gen);
+ }
+ else page=dest->getPageNum();
+ sprintf(buf, "%d", page);
+ s = strdup(buf);
+ }
+ }
break;
- case actionGoToR: {
- type = "GoToR";
- LinkGoToR*l = (LinkGoToR*)action;
- GString*g = l->getNamedDest();
- if(g)
- s = g->getCString();
- }
+ case actionGoToR: {
+ type = "GoToR";
+ LinkGoToR*l = (LinkGoToR*)action;
+ GString*g = l->getNamedDest();
+ if(g)
+ s = strdup(g->getCString());
+ }
break;
- case actionNamed: {
- type = "Named";
- LinkNamed*l = (LinkNamed*)action;
- GString*name = l->getName();
- if(name) {
- s = name->lowerCase()->getCString();
- named = name->getCString();
- if(!strchr(s,':'))
- {
- if(strstr(s, "next") || strstr(s, "forward"))
- {
- page = currentpage + 1;
- }
- else if(strstr(s, "prev") || strstr(s, "back"))
- {
- page = currentpage - 1;
- }
- else if(strstr(s, "last") || strstr(s, "end"))
- {
- page = pages[pagepos-1]; //:)
- }
- else if(strstr(s, "first") || strstr(s, "top"))
- {
- page = 1;
- }
- }
- }
- }
+ case actionNamed: {
+ type = "Named";
+ LinkNamed*l = (LinkNamed*)action;
+ GString*name = l->getName();
+ if(name) {
+ s = strdup(name->lowerCase()->getCString());
+ named = name->getCString();
+ if(!strchr(s,':'))
+ {
+ if(strstr(s, "next") || strstr(s, "forward"))
+ {
+ page = currentpage + 1;
+ }
+ else if(strstr(s, "prev") || strstr(s, "back"))
+ {
+ page = currentpage - 1;
+ }
+ else if(strstr(s, "last") || strstr(s, "end"))
+ {
+ page = pages[pagepos-1]; //:)
+ }
+ else if(strstr(s, "first") || strstr(s, "top"))
+ {
+ page = 1;
+ }
+ }
+ }
+ }
break;
- case actionLaunch: {
- type = "Launch";
- LinkLaunch*l = (LinkLaunch*)action;
- GString * str = new GString(l->getFileName());
- str->append(l->getParams());
- s = str->getCString();
- }
+ case actionLaunch: {
+ type = "Launch";
+ LinkLaunch*l = (LinkLaunch*)action;
+ GString * str = new GString(l->getFileName());
+ str->append(l->getParams());
+ s = strdup(str->getCString());
+ delete str;
+ }
break;
- case actionURI: {
- type = "URI";
- LinkURI*l = (LinkURI*)action;
- GString*g = l->getURI();
- if(g) {
- url = g->getCString();
- s = url;
- }
- }
+ case actionURI: {
+ type = "URI";
+ LinkURI*l = (LinkURI*)action;
+ GString*g = l->getURI();
+ if(g) {
+ url = g->getCString();
+ s = strdup(url);
+ }
+ }
break;
- case actionUnknown: {
- type = "Unknown";
- LinkUnknown*l = (LinkUnknown*)action;
- s = "";
- }
+ case actionUnknown: {
+ type = "Unknown";
+ LinkUnknown*l = (LinkUnknown*)action;
+ s = strdup("");
+ }
break;
- default: {
- msg("<error> Unknown link type!\n");
- break;
- }
+ default: {
+ msg("<error> Unknown link type!\n");
+ break;
+ }
}
+ if(!s) s = strdup("-?-");
+
if(!linkinfo && (page || url))
{
- msg("<notice> File contains links");
- linkinfo = 1;
+ msg("<notice> File contains links");
+ linkinfo = 1;
}
if(page>0)
{
- int t;
- for(t=0;t<pagepos;t++)
- if(pages[t]==page)
- break;
- if(t!=pagepos)
- swfoutput_linktopage(&output, t, points);
+ int t;
+ for(t=0;t<pagepos;t++)
+ if(pages[t]==page)
+ break;
+ if(t!=pagepos)
+ swfoutput_linktopage(&output, t, points);
}
else if(url)
{
- swfoutput_linktourl(&output, url, points);
+ swfoutput_linktourl(&output, url, points);
}
else if(named)
{
- swfoutput_namedlink(&output, named, points);
+ swfoutput_namedlink(&output, named, points);
}
msg("<verbose> \"%s\" link to \"%s\" (%d)\n", type, FIXNULL(s), page);
- }
+ free(s);s=0;
}
void SWFOutputDev::saveState(GfxState *state) {
clippos--;
}
-char type3Warning=0;
-
char* SWFOutputDev::searchFont(char*name)
{
int i;
char*filename=0;
+ int is_standard_font = 0;
- msg("<verbose> SearchT1Font(%s)", name);
+ msg("<verbose> SearchFont(%s)", name);
/* see if it is a pdf standard font */
for(i=0;i<sizeof(pdf2t1map)/sizeof(mapping);i++)
if(!strcmp(name, pdf2t1map[i].pdffont))
{
name = pdf2t1map[i].filename;
+ is_standard_font = 1;
break;
}
}
/* look in all font files */
for(i=0;i<fontnum;i++)
{
- if(!strstr(fonts[i], name))
+ if(strstr(fonts[i].filename, name))
{
- return fonts[i];
+ if(!fonts[i].used) {
+
+ fonts[i].used = 1;
+ if(!is_standard_font)
+ msg("<notice> Using %s for %s", fonts[i].filename, name);
+ }
+ return fonts[i].filename;
}
}
return 0;
(char)(rgb.b*255), (char)(opaq*255));
}
+void FoFiWrite(void *stream, char *data, int len)
+{
+ fwrite(data, len, 1, (FILE*)stream);
+}
+
char*SWFOutputDev::writeEmbeddedFontToFile(XRef*ref, GfxFont*font)
{
char*tmpFileName = NULL;
msg("<error> Couldn't create temporary Type 1 font file");
return 0;
}
+
+ /*if(font->isCIDFont()) {
+ GfxCIDFont* cidFont = (GfxCIDFont *)font;
+ GString c = cidFont->getCollection();
+ msg("<notice> Collection: %s", c.getCString());
+ }*/
+
if (font->getType() == fontType1C ||
font->getType() == fontCIDType0C) {
if (!(fontBuf = font->readEmbFontFile(xref, &fontLen))) {
msg("<error> Couldn't read embedded font file");
return 0;
}
+#ifdef XPDF_101
Type1CFontFile *cvt = new Type1CFontFile(fontBuf, fontLen);
cvt->convertToType1(f);
+#else
+ FoFiType1C *cvt = FoFiType1C::make(fontBuf, fontLen);
+ cvt->convertToType1(NULL, gTrue, FoFiWrite, f);
+#endif
+ //cvt->convertToCIDType0("test", f);
+ //cvt->convertToType0("test", f);
delete cvt;
gfree(fontBuf);
} else if(font->getType() == fontTrueType) {
msg("<error> Couldn't read embedded font file");
return 0;
}
+#ifdef XPDF_101
TrueTypeFontFile *cvt = new TrueTypeFontFile(fontBuf, fontLen);
cvt->writeTTF(f);
+#else
+ FoFiTrueType *cvt = FoFiTrueType::make(fontBuf, fontLen);
+ cvt->writeTTF(FoFiWrite, f);
+#endif
delete cvt;
gfree(fontBuf);
} else {
return strdup(tmpFileName);
}
+char* searchForSuitableFont(GfxFont*gfxFont)
+{
+ char*name = getFontName(gfxFont);
+ char*fontname = 0;
+ char*filename = 0;
+
+#ifdef HAVE_FONTCONFIG
+ FcPattern *pattern, *match;
+ FcResult result;
+ FcChar8 *v;
+
+ // call init ony once
+ static int fcinitcalled = false;
+ if (!fcinitcalled) {
+ fcinitcalled = true;
+ FcInit();
+ }
+
+ pattern = FcPatternBuild(NULL, FC_FAMILY, FcTypeString, name, NULL);
+ if (gfxFont->isItalic()) // check for italic
+ FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC);
+ if (gfxFont->isBold()) // check for bold
+ FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD);
+
+ // configure and match using the original font name
+ FcConfigSubstitute(0, pattern, FcMatchPattern);
+ FcDefaultSubstitute(pattern);
+ match = FcFontMatch(0, pattern, &result);
+
+ if (FcPatternGetString(match, "family", 0, &v) == FcResultMatch) {
+ // if we get an exact match
+ if (strcmp((char *)v, name) == 0) {
+ if (FcPatternGetString(match, "file", 0, &v) == FcResultMatch) {
+ filename = strdup((char*)v);
+ char *nfn = strrchr(filename, '/');
+ if(nfn) fontname = strdup(nfn+1);
+ else fontname = filename;
+ }
+ } else {
+ // initialize patterns
+ FcPatternDestroy(pattern);
+ FcPatternDestroy(match);
+
+ // now match against serif etc.
+ if (gfxFont->isSerif()) {
+ pattern = FcPatternBuild (NULL, FC_FAMILY, FcTypeString, "serif", NULL);
+ } else if (gfxFont->isFixedWidth()) {
+ pattern = FcPatternBuild (NULL, FC_FAMILY, FcTypeString, "monospace", NULL);
+ } else {
+ pattern = FcPatternBuild (NULL, FC_FAMILY, FcTypeString, "sans", NULL);
+ }
+
+ // check for italic
+ if (gfxFont->isItalic()) {
+ int bb = FcPatternAddInteger(pattern, FC_SLANT, FC_SLANT_ITALIC);
+ }
+ // check for bold
+ if (gfxFont->isBold()) {
+ int bb = FcPatternAddInteger(pattern, FC_WEIGHT, FC_WEIGHT_BOLD);
+ }
+
+ // configure and match using serif etc
+ FcConfigSubstitute (0, pattern, FcMatchPattern);
+ FcDefaultSubstitute (pattern);
+ match = FcFontMatch (0, pattern, &result);
+
+ if (FcPatternGetString(match, "file", 0, &v) == FcResultMatch) {
+ filename = strdup((char*)v);
+ char *nfn = strrchr(filename, '/');
+ if(nfn) fontname = strdup(nfn+1);
+ else fontname = filename;
+ }
+ }
+ }
+
+ //printf("FONTCONFIG: pattern");
+ //FcPatternPrint(pattern);
+ //printf("FONTCONFIG: match");
+ //FcPatternPrint(match);
+
+ FcPatternDestroy(pattern);
+ FcPatternDestroy(match);
-char* substitutetarget[256];
-char* substitutesource[256];
-int substitutepos = 0;
+ pdfswf_addfont(filename);
+ return fontname;
+#else
+ return 0;
+#endif
+}
char* SWFOutputDev::substituteFont(GfxFont*gfxFont, char* oldname)
{
- char*fontname = "Times-Roman";
- msg("<verbose> substituteFont(,%s)", FIXNULL(oldname));
- char*filename = searchFont(fontname);
+ char*fontname = 0, *filename = 0;
+ msg("<notice> subsituteFont(%s)", oldname);
+
+ if(!(fontname = searchForSuitableFont(gfxFont))) {
+ fontname = "Times-Roman";
+ }
+ filename = searchFont(fontname);
+
if(substitutepos>=sizeof(substitutesource)/sizeof(char*)) {
msg("<fatal> Too many fonts in file.");
exit(1);
if (!gfxFont) {
return;
}
- char * fontname = getFontName(gfxFont);
+ char * fontid = getFontID(gfxFont);
int t;
/* first, look if we substituted this font before-
this way, we don't initialize the T1 Fonts
too often */
for(t=0;t<substitutepos;t++) {
- if(!strcmp(fontname, substitutesource[t])) {
- fontname = substitutetarget[t];
+ if(!strcmp(fontid, substitutesource[t])) {
+ fontid = substitutetarget[t];
break;
}
}
/* second, see if swfoutput already has this font
cached- if so, we are done */
- if(swfoutput_queryfont(&output, fontname))
+ if(swfoutput_queryfont(&output, fontid))
{
- swfoutput_setfont(&output, fontname, 0);
+ swfoutput_setfont(&output, fontid, 0);
- msg("<debug> updateFont(%s) [cached]", fontname);
+ msg("<debug> updateFont(%s) [cached]", fontid);
return;
}
// look for Type 3 font
- if (!type3Warning && gfxFont->getType() == fontType3) {
- type3Warning = gTrue;
- showFontError(gfxFont, 2);
+ if (gfxFont->getType() == fontType3) {
+ if(!type3Warning) {
+ type3Warning = gTrue;
+ showFontError(gfxFont, 2);
+ }
+ return;
}
/* now either load the font, or find a substitution */
int del = 0;
if(embedded &&
(gfxFont->getType() == fontType1 ||
- gfxFont->getType() == fontCIDType0C ||
gfxFont->getType() == fontType1C ||
+ //gfxFont->getType() == fontCIDType0C ||
gfxFont->getType() == fontTrueType ||
gfxFont->getType() == fontCIDType2
))
if(!fileName) showFontError(gfxFont,0);
else del = 1;
} else {
+ char * fontname = getFontName(gfxFont);
fileName = searchFont(fontname);
if(!fileName) showFontError(gfxFont,0);
}
- if(!fileName)
- fileName = substituteFont(gfxFont, fontname);
+ if(!fileName) {
+ char * fontname = getFontName(gfxFont);
+ 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*/};
+ msg("<notice> Font is now %s (%s)", fontid, fileName);
+ }
if(!fileName) {
- msg("<error> Couldn't set font %s\n", fontname);
+ msg("<error> Couldn't set font %s\n", fontid);
return;
}
- msg("<verbose> updateFont(%s) -> %s", fontname, fileName);
+ msg("<verbose> updateFont(%s) -> %s", fontid, fileName);
+ dumpFontInfo("<verbose>", gfxFont);
- swfoutput_setfont(&output, fontname, fileName);
-
+ swfoutput_setfont(&output, fontid, fileName);
+
if(fileName && del)
unlinkfont(fileName);
}
-int pic_xids[1024];
-int pic_yids[1024];
-int pic_ids[1024];
-int pic_width[1024];
-int pic_height[1024];
-int picpos = 0;
-int pic_id = 0;
-
#define SQR(x) ((x)*(x))
unsigned char* antialize(unsigned char*data, int width, int height, int newwidth, int newheight, int palettesize)
void pdfswf_init(char*filename, char*userPassword)
{
- GString *fileName = new GString(filename);
- GString *userPW;
- Object info;
-
- // read config file
- globalParams = new GlobalParams("");
-
- // open PDF file
- if (userPassword && userPassword[0]) {
- userPW = new GString(userPassword);
- } else {
- userPW = NULL;
- }
- doc = new PDFDoc(fileName, userPW);
- if (userPW) {
- delete userPW;
- }
- if (!doc->isOk()) {
- exit(1);
- }
+ GString *fileName = new GString(filename);
+ GString *userPW;
+ Object info;
- // print doc info
- doc->getDocInfo(&info);
- if (info.isDict() &&
- (screenloglevel>=LOGLEVEL_NOTICE)) {
- printInfoString(info.getDict(), "Title", "Title: %s\n");
- printInfoString(info.getDict(), "Subject", "Subject: %s\n");
- printInfoString(info.getDict(), "Keywords", "Keywords: %s\n");
- printInfoString(info.getDict(), "Author", "Author: %s\n");
- printInfoString(info.getDict(), "Creator", "Creator: %s\n");
- printInfoString(info.getDict(), "Producer", "Producer: %s\n");
- printInfoDate(info.getDict(), "CreationDate", "CreationDate: %s\n");
- printInfoDate(info.getDict(), "ModDate", "ModDate: %s\n");
- printf("Pages: %d\n", doc->getNumPages());
- printf("Linearized: %s\n", doc->isLinearized() ? "yes" : "no");
- printf("Encrypted: ");
- if (doc->isEncrypted()) {
- printf("yes (print:%s copy:%s change:%s addNotes:%s)\n",
- doc->okToPrint() ? "yes" : "no",
- doc->okToCopy() ? "yes" : "no",
- doc->okToChange() ? "yes" : "no",
- doc->okToAddNotes() ? "yes" : "no");
+ // read config file
+ globalParams = new GlobalParams("");
+
+ // open PDF file
+ if (userPassword && userPassword[0]) {
+ userPW = new GString(userPassword);
} else {
- printf("no\n");
+ userPW = NULL;
}
- }
- info.free();
-
- numpages = doc->getNumPages();
- if (doc->isEncrypted()) {
- /*ERROR: This pdf is encrypted, and disallows copying.
- Due to the DMCA, paragraph 1201, (2) A-C, circumventing
- a technological measure that efficively controls access to
- a protected work is violating American law.
- See www.eff.org for more information about DMCA issues.
- */
- if(!doc->okToCopy()) {
- printf("PDF disallows copying. Bailing out.\n");
- exit(1); //bail out
- }
- if(!doc->okToChange() || !doc->okToAddNotes())
- swfoutput_setprotected();
- }
+ doc = new PDFDoc(fileName, userPW);
+ if (userPW) {
+ delete userPW;
+ }
+ if (!doc->isOk()) {
+ exit(1);
+ }
+
+ // print doc info
+ doc->getDocInfo(&info);
+ if (info.isDict() &&
+ (screenloglevel>=LOGLEVEL_NOTICE)) {
+ printInfoString(info.getDict(), "Title", "Title: %s\n");
+ printInfoString(info.getDict(), "Subject", "Subject: %s\n");
+ printInfoString(info.getDict(), "Keywords", "Keywords: %s\n");
+ printInfoString(info.getDict(), "Author", "Author: %s\n");
+ printInfoString(info.getDict(), "Creator", "Creator: %s\n");
+ printInfoString(info.getDict(), "Producer", "Producer: %s\n");
+ printInfoDate(info.getDict(), "CreationDate", "CreationDate: %s\n");
+ printInfoDate(info.getDict(), "ModDate", "ModDate: %s\n");
+ printf("Pages: %d\n", doc->getNumPages());
+ printf("Linearized: %s\n", doc->isLinearized() ? "yes" : "no");
+ printf("Encrypted: ");
+ if (doc->isEncrypted()) {
+ printf("yes (print:%s copy:%s change:%s addNotes:%s)\n",
+ doc->okToPrint() ? "yes" : "no",
+ doc->okToCopy() ? "yes" : "no",
+ doc->okToChange() ? "yes" : "no",
+ doc->okToAddNotes() ? "yes" : "no");
+ } else {
+ printf("no\n");
+ }
+ }
+ info.free();
+
+ numpages = doc->getNumPages();
+ int protect = 0;
+ if (doc->isEncrypted()) {
+ if(!doc->okToCopy()) {
+ printf("PDF disallows copying. Terminating.\n");
+ exit(1); //bail out
+ }
+ if(!doc->okToChange() || !doc->okToAddNotes())
+ protect = 1;
+ }
+
+ if(protect)
+ swfoutput_setparameter("protect", "1");
- output = new SWFOutputDev();
- output->startDoc(doc->getXRef());
+ output = new SWFOutputDev();
+ output->startDoc(doc->getXRef());
}
void pdfswf_setparameter(char*name, char*value)
{
- if(!strcmp(name, "drawonlyshapes")) {
- drawonlyshapes = atoi(value);
- } else if(!strcmp(name, "ignoredraworder")) {
- ignoredraworder = atoi(value);
- } else if(!strcmp(name, "linksopennewwindow")) {
- opennewwindow = atoi(value);
- } else if(!strcmp(name, "storeallcharacters")) {
- storeallcharacters = atoi(value);
- } else if(!strcmp(name, "enablezlib")) {
- enablezlib = atoi(value);
- } else if(!strcmp(name, "insertstop")) {
- insertstoptag = atoi(value);
- } else if(!strcmp(name, "flashversion")) {
- flashversion = atoi(value);
- } else if(!strcmp(name, "jpegquality")) {
- int val = atoi(value);
- if(val<0) val=0;
- if(val>100) val=100;
- jpegquality = val;
- } else if(!strcmp(name, "outputfilename")) {
+ if(!strcmp(name, "outputfilename")) {
swffilename = value;
} else if(!strcmp(name, "caplinewidth")) {
caplinewidth = atof(value);
- } else if(!strcmp(name, "splinequality")) {
- int v = atoi(value);
- v = 500-(v*5); // 100% = 0.25 pixel, 0% = 25 pixel
- if(v<1) v = 1;
- splinemaxerror = v;
- } else if(!strcmp(name, "fontquality")) {
- int v = atoi(value);
- v = 500-(v*5); // 100% = 0.25 pixel, 0% = 25 pixel
- if(v<1) v = 1;
- fontsplinemaxerror = v;
+ } else if(!strcmp(name, "zoom")) {
+ zoom = atoi(value);
} else {
- fprintf(stderr, "unknown parameter: %s (=%s)\n", name, value);
+ swfoutput_setparameter(name, value);
}
}
void pdfswf_addfont(char*filename)
{
- fonts[fontnum++] = filename;
-}
-
-void pdfswf_drawonlyshapes()
-{
- drawonlyshapes = 1;
-}
-
-void pdfswf_ignoredraworder()
-{
- ignoredraworder = 1;
-}
-
-void pdfswf_linksopennewwindow()
-{
- opennewwindow = 1;
-}
-
-void pdfswf_storeallcharacters()
-{
- storeallcharacters = 1;
-}
-
-void pdfswf_enablezlib()
-{
- enablezlib = 1;
-}
-
-void pdfswf_jpegquality(int val)
-{
- if(val<0) val=0;
- if(val>100) val=100;
- jpegquality = val;
-}
-
-void pdfswf_setoutputfilename(char*_filename)
-{
- swffilename = _filename;
-}
-
-void pdfswf_insertstop()
-{
- insertstoptag = 1;
-}
-
-void pdfswf_setversion(int n)
-{
- flashversion = n;
+ fontfile_t f;
+ memset(&f, 0, sizeof(fontfile_t));
+ f.filename = filename;
+ fonts[fontnum++] = f;
}
+void pdfswf_setoutputfilename(char*_filename) { swffilename = _filename; }
void pdfswf_convertpage(int page)
{
for(t=0;t<pagepos;t++)
{
currentpage = pages[t];
- doc->displayPage((OutputDev*)output, currentpage, /*dpi*/72, /*rotate*/0, /*doLinks*/(int)1);
+#ifdef XPDF_101
+ doc->displayPage((OutputDev*)output, currentpage, /*zoom*/zoom, /*rotate*/0, /*doLinks*/(int)1);
+#else
+ doc->displayPage((OutputDev*)output, currentpage, zoom, zoom, /*rotate*/0, true, /*doLinks*/(int)1);
+#endif
}
}
-
int pdfswf_numpages()
{
return doc->getNumPages();
}
-int closed=0;
void pdfswf_close()
{
msg("<debug> pdfswf.cc: pdfswf_close()");
- delete output;
- delete doc;
+ delete output; output=0;
+ delete doc; doc=0;
+ free(pages); pages = 0;
//freeParams();
// check for memory leaks
Object::memCheck(stderr);