Commit 6baed393 authored by Albert Astals Cid's avatar Albert Astals Cid
Browse files

The big xpdf 3.02 merge, it's mostly working except

Annot has still to be merged, i'll leave that to jrebetez
DCTStream and FlateStream classes have not been tested
ArthurOutputDev had some code commented, but as it was nto working it's not crucial
UGooString got removed as i got clear it was not needed, yay!
HtmlOutputDev won't detect links as the base outputdev changed signature
Did not test CairoOutputDev but i have 0 knowledge of Cairo so i need someone here anyway
glib frontend has some nasty warnings probably due to changed signatures, have a look
And in all i'm quite happy of the merge as it renders "something" and my kpdf port all it had was crashes :D
parent 775eb470
This diff is collapsed.
......@@ -34,9 +34,12 @@ public:
// Create a FoFiTrueType object from a file on disk.
static FoFiTrueType *load(char *fileName, int faceIndexA=0);
FoFiTrueType(char *fileA, int lenA, GBool freeFileDataA, int faceIndexA=0);
virtual ~FoFiTrueType();
// Returns true if this an OpenType font containing CFF data, false
// if it's a TrueType font (or OpenType font with TrueType data).
GBool isOpenTypeCFF() { return openTypeCFF; }
// Return the number of cmaps defined by this font.
int getNumCmaps();
......@@ -58,6 +61,11 @@ public:
// font does not have a post table.
int mapNameToGID(char *name);
// Return the mapping from CIDs to GIDs, and return the number of
// CIDs in *<nCIDs>. This is only useful for CID fonts. (Only
// useful for OpenType CFF fonts.)
Gushort *getCIDToGIDMap(int *nCIDs);
// Returns the least restrictive embedding licensing right (as
// defined by the TrueType spec):
// * 4: OS/2 table is missing or invalid
......@@ -73,38 +81,63 @@ public:
// <encoding> array specifies the mapping from char codes to names.
// If <encoding> is NULL, the encoding is unknown or undefined. The
// <codeToGID> array specifies the mapping from char codes to GIDs.
// (Not useful for OpenType CFF fonts.)
void convertToType42(char *psName, char **encoding,
Gushort *codeToGID,
FoFiOutputFunc outputFunc, void *outputStream);
// Convert to a Type 1 font, suitable for embedding in a PostScript
// file. This is only useful with 8-bit fonts. If <newEncoding> is
// not NULL, it will be used in place of the encoding in the Type 1C
// font. If <ascii> is true the eexec section will be hex-encoded,
// otherwise it will be left as binary data. If <psName> is
// non-NULL, it will be used as the PostScript font name. (Only
// useful for OpenType CFF fonts.)
void convertToType1(char *psName, char **newEncoding, GBool ascii,
FoFiOutputFunc outputFunc, void *outputStream);
// Convert to a Type 2 CIDFont, suitable for embedding in a
// PostScript file. <psName> will be used as the PostScript font
// name (so we don't need to depend on the 'name' table in the
// font). The <cidMap> array maps CIDs to GIDs; it has <nCIDs>
// entries.
// entries. (Not useful for OpenType CFF fonts.)
void convertToCIDType2(char *psName, Gushort *cidMap, int nCIDs,
GBool needVerticalMetrics,
FoFiOutputFunc outputFunc, void *outputStream);
// Convert to a Type 0 CIDFont, suitable for embedding in a
// PostScript file. <psName> will be used as the PostScript font
// name. (Only useful for OpenType CFF fonts.)
void convertToCIDType0(char *psName,
FoFiOutputFunc outputFunc, void *outputStream);
// Convert to a Type 0 (but non-CID) composite font, suitable for
// embedding in a PostScript file. <psName> will be used as the
// PostScript font name (so we don't need to depend on the 'name'
// table in the font). The <cidMap> array maps CIDs to GIDs; it has
// <nCIDs> entries.
// <nCIDs> entries. (Not useful for OpenType CFF fonts.)
void convertToType0(char *psName, Gushort *cidMap, int nCIDs,
GBool needVerticalMetrics,
FoFiOutputFunc outputFunc, void *outputStream);
// Convert to a Type 0 (but non-CID) composite font, suitable for
// embedding in a PostScript file. <psName> will be used as the
// PostScript font name. (Only useful for OpenType CFF fonts.)
void convertToType0(char *psName,
FoFiOutputFunc outputFunc, void *outputStream);
// Write a clean TTF file, filling in missing tables and correcting
// various other errors. If <name> is non-NULL, the font is renamed
// to <name>. If <codeToGID> is non-NULL, the font is re-encoded,
// using a Windows Unicode cmap. If <name> is NULL and the font is
// complete and correct, it will be written unmodified.
// complete and correct, it will be written unmodified. (Not useful
// for OpenType CFF fonts.)
void writeTTF(FoFiOutputFunc outputFunc, void *outputStream,
char *name = NULL, Gushort *codeToGID = NULL);
private:
FoFiTrueType(char *fileA, int lenA, GBool freeFileDataA, int faceIndexA);
void cvtEncoding(char **encoding,
FoFiOutputFunc outputFunc,
void *outputStream);
......@@ -131,6 +164,7 @@ private:
int locaFmt;
int bbox[4];
GooHash *nameToGID;
GBool openTypeCFF;
GBool parsedOk;
int faceIndex;
......
......@@ -75,7 +75,7 @@ char **FoFiType1::getEncoding() {
void FoFiType1::writeEncoded(char **newEncoding,
FoFiOutputFunc outputFunc, void *outputStream) {
char buf[512];
char *line;
char *line, *line2, *p;
int i;
// copy everything up to the encoding
......@@ -101,19 +101,57 @@ void FoFiType1::writeEncoded(char **newEncoding,
}
(*outputFunc)(outputStream, "readonly def\n", 13);
// copy everything after the encoding
// find the end of the encoding data
//~ this ought to parse PostScript tokens
if (!strncmp(line, "/Encoding StandardEncoding def", 30)) {
line = getNextLine(line);
} else {
for (line = getNextLine(line);
line && strncmp(line, "readonly def", 12);
line = getNextLine(line)) ;
if (line) {
line = getNextLine(line);
// skip "/Encoding" + one whitespace char,
// then look for 'def' preceded by PostScript whitespace
p = line + 10;
line = NULL;
for (; p < (char *)file + len; ++p) {
if ((*p == ' ' || *p == '\t' || *p == '\x0a' ||
*p == '\x0d' || *p == '\x0c' || *p == '\0') &&
p + 4 <= (char *)file + len &&
!strncmp(p + 1, "def", 3)) {
line = p + 4;
break;
}
}
}
// some fonts have two /Encoding entries in their dictionary, so we
// check for a second one here
if (line) {
(*outputFunc)(outputStream, line, ((char *)file + len) - line);
for (line2 = line, i = 0;
i < 20 && line2 && strncmp(line2, "/Encoding", 9);
line2 = getNextLine(line2), ++i) ;
if (i < 20 && line2) {
(*outputFunc)(outputStream, line, line2 - line);
if (!strncmp(line2, "/Encoding StandardEncoding def", 30)) {
line = getNextLine(line2);
} else {
// skip "/Encoding" + one whitespace char,
// then look for 'def' preceded by PostScript whitespace
p = line2 + 10;
line = NULL;
for (; p < (char *)file + len; ++p) {
if ((*p == ' ' || *p == '\t' || *p == '\x0a' ||
*p == '\x0d' || *p == '\x0c' || *p == '\0') &&
p + 4 <= (char *)file + len &&
!strncmp(p + 1, "def", 3)) {
line = p + 4;
break;
}
}
}
}
// copy everything after the encoding
if (line) {
(*outputFunc)(outputStream, line, ((char *)file + len) - line);
}
}
}
......@@ -178,8 +216,15 @@ void FoFiType1::parse() {
if (*p2) {
c = *p2;
*p2 = '\0';
if ((code = atoi(p)) < 256) {
*p2 = c;
code = atoi(p);
*p2 = c;
if (code == 8 && *p2 == '#') {
code = 0;
for (++p2; *p2 >= '0' && *p2 <= '7'; ++p2) {
code = code * 8 + (*p2 - '0');
}
}
if (code < 256) {
for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
if (*p == '/') {
++p;
......
This diff is collapsed.
......@@ -138,7 +138,6 @@ public:
// Create a FoFiType1C object from a file on disk.
static FoFiType1C *load(char *fileName);
FoFiType1C(char *fileA, int lenA, GBool freeFileDataA);
virtual ~FoFiType1C();
// Return the font name.
......@@ -156,8 +155,9 @@ public:
// file. This is only useful with 8-bit fonts. If <newEncoding> is
// not NULL, it will be used in place of the encoding in the Type 1C
// font. If <ascii> is true the eexec section will be hex-encoded,
// otherwise it will be left as binary data.
void convertToType1(char **newEncoding, GBool ascii,
// otherwise it will be left as binary data. If <psName> is non-NULL,
// it will be used as the PostScript font name.
void convertToType1(char *psName, char **newEncoding, GBool ascii,
FoFiOutputFunc outputFunc, void *outputStream);
// Convert to a Type 0 CIDFont, suitable for embedding in a
......@@ -174,6 +174,7 @@ public:
private:
FoFiType1C(char *fileA, int lenA, GBool freeFileDataA);
void eexecCvtGlyph(Type1CEexecBuf *eb, char *glyphName,
int offset, int nBytes,
Type1CIndex *subrIdx,
......
......@@ -16,8 +16,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <UGooString.h>
#include "poppler.h"
#include "poppler-private.h"
......@@ -267,7 +265,7 @@ dest_new_goto (PopplerDocument *document,
}
static PopplerDest *
dest_new_named (UGooString *named_dest)
dest_new_named (GooString *named_dest)
{
PopplerDest *dest;
gchar *name;
......@@ -293,7 +291,7 @@ build_goto_dest (PopplerDocument *document,
LinkGoTo *link)
{
LinkDest *link_dest;
UGooString *named_dest;
GooString *named_dest;
/* Return if it isn't OK */
if (! link->isOk ()) {
......@@ -318,7 +316,7 @@ build_goto_remote (PopplerAction *action,
LinkGoToR *link)
{
LinkDest *link_dest;
UGooString *named_dest;
GooString *named_dest;
/* Return if it isn't OK */
if (! link->isOk ()) {
......
......@@ -28,7 +28,6 @@
#include <Stream.h>
#include <FontInfo.h>
#include <PDFDocEncoding.h>
#include <UGooString.h>
#include "poppler.h"
#include "poppler-private.h"
......@@ -388,12 +387,12 @@ poppler_document_find_dest (PopplerDocument *document,
{
PopplerDest *dest = NULL;
LinkDest *link_dest = NULL;
UGooString *g_link_name;
GooString *g_link_name;
g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), NULL);
g_return_val_if_fail (link_name != NULL, NULL);
g_link_name = new UGooString (link_name);
g_link_name = new GooString (link_name);
if (g_link_name) {
link_dest = document->doc->findDest (g_link_name);
......
......@@ -18,7 +18,6 @@
#include "Catalog.h"
#include "Gfx.h"
#include "Lexer.h"
#include "UGooString.h"
#include "Annot.h"
#include "GfxFont.h"
#include "CharCodeToUnicode.h"
......@@ -334,7 +333,7 @@ void Annot::generateAppearance(Dict *acroForm, Dict *dict) {
Object obj3, obj4;
//--
bool found = false;
if (obj1.dictLookup(*fontName, &obj3)->isDict() && obj3.dictLookup("Type", &obj4)->isName("Font")) {
if (obj1.dictLookup(fontName->getCString(), &obj3)->isDict() && obj3.dictLookup("Type", &obj4)->isName("Font")) {
found = true;
}
if (!found) { //font not found in DR, try to lookup in each entry BaseFont/Name
......@@ -364,7 +363,7 @@ void Annot::generateAppearance(Dict *acroForm, Dict *dict) {
}
if (found) {
obj4.free();
obj1.dictLookupNF(*fontName, &obj4);
obj1.dictLookupNF(fontName->getCString(), &obj4);
Ref r;
if (obj4.isRef()) r = obj4.getRef();
else r.gen = r.num = 0;
......@@ -476,7 +475,8 @@ void Annot::generateAppearance(Dict *acroForm, Dict *dict) {
void Annot::draw(Gfx *gfx) {
Object obj;
if (appearance.fetch(xref, &obj)->isStream()) {
gfx->doAnnot(&obj, xMin, yMin, xMax, yMax);
#warning TODO!!!
// gfx->doAnnot(&obj, xMin, yMin, xMax, yMax);
}
obj.free();
}
......
......@@ -20,6 +20,42 @@ class CharCodeToUnicode;
class GfxFont;
class FormWidget;
//------------------------------------------------------------------------
// AnnotBorderStyle
//------------------------------------------------------------------------
enum AnnotBorderType {
annotBorderSolid,
annotBorderDashed,
annotBorderBeveled,
annotBorderInset,
annotBorderUnderlined
};
class AnnotBorderStyle {
public:
AnnotBorderStyle(AnnotBorderType typeA, double widthA,
double *dashA, int dashLengthA,
double rA, double gA, double bA);
~AnnotBorderStyle();
AnnotBorderType getType() { return type; }
double getWidth() { return width; }
void getDash(double **dashA, int *dashLengthA)
{ *dashA = dash; *dashLengthA = dashLength; }
void getColor(double *rA, double *gA, double *bA)
{ *rA = r; *gA = g; *bA = b; }
private:
AnnotBorderType type;
double width;
double *dash;
int dashLength;
double r, g, b;
};
//------------------------------------------------------------------------
// Annot
//------------------------------------------------------------------------
......
......@@ -241,6 +241,8 @@ void ArthurOutputDev::updateStrokeOpacity(GfxState *state)
void ArthurOutputDev::updateFont(GfxState *state)
{
#warning fix this, probably update with updated code from SplashOutputdev
/*
GfxFont *gfxFont;
GfxFontType fontType;
SplashOutFontFileID *id;
......@@ -403,7 +405,7 @@ void ArthurOutputDev::updateFont(GfxState *state)
err2:
delete id;
err1:
err1:*/
return;
}
......@@ -513,9 +515,12 @@ void ArthurOutputDev::drawChar(GfxState *state, double x, double y,
qPath.quadTo(x0+fontPath->pts[i].x, y0+fontPath->pts[i].y,
x0+fontPath->pts[i+1].x, y0+fontPath->pts[i+1].y);
++i;
} else if (fontPath->flags[i] & splashPathArcCW) {
qDebug() << "Need to implement arc";
} else {
}
#warning FIX THIS
// else if (fontPath->flags[i] & splashPathArcCW) {
// qDebug() << "Need to implement arc";
// }
else {
qPath.lineTo(x0+fontPath->pts[i].x, y0+fontPath->pts[i].y);
}
if (fontPath->flags[i] & splashPathLast) {
......
......@@ -2,7 +2,7 @@
//
// Catalog.cc
//
// Copyright 1996-2003 Glyph & Cog, LLC
// Copyright 1996-2007 Glyph & Cog, LLC
//
//========================================================================
......@@ -23,23 +23,17 @@
#include "Error.h"
#include "Link.h"
#include "PageLabelInfo.h"
#include "UGooString.h"
#include "Catalog.h"
#include "Form.h"
// This define is used to limit the depth of recursive readPageTree calls
// This is needed because the page tree nodes can reference their parents
// leaving us in an infinite loop
// Most sane pdf documents don't have a call depth higher than 10
#define MAX_CALL_DEPTH 1000
//------------------------------------------------------------------------
// Catalog
//------------------------------------------------------------------------
Catalog::Catalog(XRef *xrefA) {
Object catDict, pagesDict;
Object catDict, pagesDict, pagesDictRef;
Object obj, obj2;
char *alreadyRead;
int numPages0;
int i;
......@@ -91,7 +85,16 @@ Catalog::Catalog(XRef *xrefA) {
pageRefs[i].num = -1;
pageRefs[i].gen = -1;
}
numPages = readPageTree(pagesDict.getDict(), NULL, 0, 0);
alreadyRead = (char *)gmalloc(xref->getNumObjects());
memset(alreadyRead, 0, xref->getNumObjects());
if (catDict.dictLookupNF("Pages", &pagesDictRef)->isRef() &&
pagesDictRef.getRefNum() >= 0 &&
pagesDictRef.getRefNum() < xref->getNumObjects()) {
alreadyRead[pagesDictRef.getRefNum()] = 1;
}
pagesDictRef.free();
numPages = readPageTree(pagesDict.getDict(), NULL, 0, alreadyRead);
gfree(alreadyRead);
if (numPages != numPages0) {
error(-1, "Page count in top-level pages object is incorrect");
}
......@@ -234,7 +237,8 @@ GooString *Catalog::readMetadata() {
return s;
}
int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start, int callDepth) {
int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start,
char *alreadyRead) {
Object kids;
Object kid;
Object kidRef;
......@@ -250,6 +254,17 @@ int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start, int call
goto err1;
}
for (i = 0; i < kids.arrayGetLength(); ++i) {
kids.arrayGetNF(i, &kidRef);
if (kidRef.isRef() &&
kidRef.getRefNum() >= 0 &&
kidRef.getRefNum() < xref->getNumObjects()) {
if (alreadyRead[kidRef.getRefNum()]) {
error(-1, "Loop in Pages tree");
kidRef.free();
continue;
}
alreadyRead[kidRef.getRefNum()] = 1;
}
kids.arrayGet(i, &kid);
if (kid.isDict("Page")) {
attrs2 = new PageAttrs(attrs1, kid.getDict());
......@@ -269,28 +284,23 @@ int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start, int call
}
}
pages[start] = page;
kids.arrayGetNF(i, &kidRef);
if (kidRef.isRef()) {
pageRefs[start].num = kidRef.getRefNum();
pageRefs[start].gen = kidRef.getRefGen();
}
kidRef.free();
++start;
// This should really be isDict("Pages"), but I've seen at least one
// PDF file where the /Type entry is missing.
} else if (kid.isDict()) {
if (callDepth > MAX_CALL_DEPTH) {
error(-1, "Limit of %d recursive calls reached while reading the page tree. If your document is correct and not a test to try to force a crash, please report a bug.", MAX_CALL_DEPTH);
} else {
if ((start = readPageTree(kid.getDict(), attrs1, start, callDepth + 1))
< 0)
goto err2;
}
if ((start = readPageTree(kid.getDict(), attrs1, start, alreadyRead))
< 0)
goto err2;
} else {
error(-1, "Kid object (page %d) is wrong type (%s)",
start+1, kid.getTypeName());
}
kid.free();
kidRef.free();
}
delete attrs1;
kids.free();
......@@ -317,7 +327,7 @@ int Catalog::findPage(int num, int gen) {
return 0;
}
LinkDest *Catalog::findDest(UGooString *name) {
LinkDest *Catalog::findDest(GooString *name) {
LinkDest *dest;
Object obj1, obj2;
GBool found;
......@@ -325,7 +335,7 @@ LinkDest *Catalog::findDest(UGooString *name) {
// try named destination dictionary then name tree
found = gFalse;
if (dests.isDict()) {
if (!dests.dictLookup(*name, &obj1)->isNull())
if (!dests.dictLookup(name->getCString(), &obj1)->isNull())
found = gTrue;
else
obj1.free();
......@@ -377,7 +387,7 @@ EmbFile *Catalog::embeddedFile(int i)
delete[] descString;
GooString *createDate = new GooString();
GooString *modDate = new GooString();
Stream *efStream;
Stream *efStream = NULL;
if (obj.isRef()) {
if (obj.fetch(xref, &efDict)->isDict()) {
// efDict matches Table 3.40 in the PDF1.6 spec
......@@ -452,7 +462,7 @@ EmbFile *Catalog::embeddedFile(int i)
return embeddedFile;
}
NameTree::NameTree(void)
NameTree::NameTree()
{
size = 0;
length = 0;
......@@ -460,23 +470,20 @@ NameTree::NameTree(void)
}
NameTree::Entry::Entry(Array *array, int index) {
GooString n;
if (!array->getString(index, &n) || !array->getNF(index + 1, &value)) {
if (!array->getString(index, &name) || !array->getNF(index + 1, &value)) {
Object aux;
array->get(index, &aux);
if (aux.isString() && array->getNF(index + 1, &value) )
{
n.append(aux.getString());
name.append(aux.getString());
}
else
error(-1, "Invalid page tree");
}
name = new UGooString(n);
}
NameTree::Entry::~Entry() {
value.free();
delete name;
}
void NameTree::addEntry(Entry *entry)
......@@ -531,13 +538,13 @@ void NameTree::parse(Object *tree) {
int NameTree::Entry::cmp(const void *voidKey, const void *voidEntry)
{
UGooString *key = (UGooString *) voidKey;
GooString *key = (GooString *) voidKey;
Entry *entry = *(NameTree::Entry **) voidEntry;
return key->cmp(entry->name);
return key->cmp(&entry->name);
}
GBool NameTree::lookup(UGooString *name, Object *obj)
GBool NameTree::lookup(GooString *name, Object *obj)
{
Entry **entry;
char *cname;
......@@ -565,10 +572,10 @@ Object NameTree::getValue(int index)
}
}
UGooString *NameTree::getName(int index)
GooString *NameTree::getName(int index)
{
if (index < length) {
return entries[index]->name;
return &entries[index]->name;
} else {
return NULL;
}
......
......@@ -2,7 +2,7 @@
//
// Catalog.h
//
// Copyright 1996-2003 Glyph & Cog, LLC
// Copyright 1996-2007 Glyph & Cog, LLC
//
//========================================================================
......@@ -19,7 +19,6 @@ class Page;
class PageAttrs;
struct Ref;
class LinkDest;
class UGooString;
class PageLabelInfo;
class Form;
......@@ -32,18 +31,18 @@ public:
NameTree();
void init(XRef *xref, Object *tree);
void parse(Object *tree);
GBool lookup(UGooString *name, Object *obj);
GBool lookup(GooString *name, Object *obj);
void free();
int numEntries() { return length; };
// iterator accessor
Object getValue(int i);
UGooString *getName(int i);
GooString *getName(int i);
private: