#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 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);
// 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()?
{
return gTrue;
}
+GBool SWFOutputDev::useGradients()
+{
+ if(!gradientinfo)
+ {
+ msg("<notice> File contains gradients");
+ gradientinfo = 1;
+ }
+ return gTrue;
+}
void SWFOutputDev::beginString(GfxState *state, GString *s)
{
x1 = x;
y1 = y;
state->transform(x, y, &x1, &y1);
-
+
Unicode u=0;
- if(_u)
+ if(_u && uLen)
u = *_u;
-
+
/* find out the character name */
char*name=0;
if(font->isCIDFont() && u) {
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);
}
if(rot!=0)
msg("<verbose> page is rotated %d degrees\n", rot);
- msg("<notice> processing page %d", pageNum);
-
/* state->transform(state->getX1(),state->getY1(),&x1,&y1);
state->transform(state->getX2(),state->getY2(),&x2,&y2);
Use CropBox, not MediaBox, as page size
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, swffilename);
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)
swfcoord points[5];
int x, y;
+#ifdef XPDF_101
link->getBorder(&x1, &y1, &x2, &y2, &w);
+#else
+ link->getRect(&x1, &y1, &x2, &y2);
+#endif
// if (w > 0)
{
rgb.r = 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 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;
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 {
char* substitutesource[256];
int substitutepos = 0;
+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);
+
+ 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);
}
// 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 */
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) {
swffilename = value;
} else if(!strcmp(name, "caplinewidth")) {
caplinewidth = atof(value);
+ } else if(!strcmp(name, "zoom")) {
+ zoom = atoi(value);
} else {
swfoutput_setparameter(name, value);
}
fonts[fontnum++] = f;
}
-/* TODO: get rid of this */
-void pdfswf_drawonlyshapes() { pdfswf_setparameter("drawonlyshapes", "1"); }
-void pdfswf_ignoredraworder() { pdfswf_setparameter("ignoredraworder", "1"); }
-void pdfswf_linksopennewwindow() { pdfswf_setparameter("opennewwindow", "1"); }
-void pdfswf_storeallcharacters() { pdfswf_setparameter("storeallcharacters", "1"); }
-void pdfswf_enablezlib() { pdfswf_setparameter("enablezlib", "1"); }
void pdfswf_setoutputfilename(char*_filename) { swffilename = _filename; }
-void pdfswf_insertstop() { pdfswf_setparameter("insertstoptag", "1"); }
-void pdfswf_jpegquality(int val) {
- char tmp[32];
- sprintf(tmp, "%d", val);
- pdfswf_setparameter("jpegquality", tmp);
-}
-void pdfswf_setversion(int n) {
- char tmp[32];
- sprintf(tmp, "%d", n);
- pdfswf_setparameter("flashversion", tmp);
-}
-
-
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()