[poppler] poppler/GfxFont.cc poppler/GfxFont.h
Albert Astals Cid
aacid at kemper.freedesktop.org
Sun Jan 21 21:26:27 UTC 2018
poppler/GfxFont.cc | 125 +++++++++++++++++++++++++++++++++++++++++++++++++----
poppler/GfxFont.h | 4 +
2 files changed, 120 insertions(+), 9 deletions(-)
New commits:
commit f65f60e5d3f5e4109a79212a9994b5096a2a2a8d
Author: Jason Crain <jason at inspiresomeone.us>
Date: Thu Jan 18 11:57:33 2018 -0600
GfxFontDict: merge reference generation from xpdf 4.00
The GfxFontDict constructor generates a fake indirect reference if the
font dictionary doesn't have a real indirect reference. It sometimes
assigns the same reference to two different fonts leading to a wrong
font being used. XPDF 4.00 fixes this by using the hash of the font
data to create the fake reference.
https://bugs.freedesktop.org/show_bug.cgi?id=104565
diff --git a/poppler/GfxFont.cc b/poppler/GfxFont.cc
index 27be71d0..9ef26234 100644
--- a/poppler/GfxFont.cc
+++ b/poppler/GfxFont.cc
@@ -2443,16 +2443,16 @@ GfxFontDict::GfxFontDict(XRef *xref, Ref *fontDictRef, Dict *fontDict) {
if (obj2.isDict()) {
if (obj1.isRef()) {
r = obj1.getRef();
- } else {
- // no indirect reference for this font, so invent a unique one
- // (legal generation numbers are five digits, so any 6-digit
- // number would be safe)
+ } else if (fontDictRef) {
+ // legal generation numbers are five digits, so we use a
+ // 6-digit number here
+ r.gen = 100000 + fontDictRef->num;
r.num = i;
- if (fontDictRef) {
- r.gen = 100000 + fontDictRef->num;
- } else {
- r.gen = 999999;
- }
+ } else {
+ // no indirect reference for this font, or for the containing
+ // font dict, so hash the font and use that
+ r.gen = 100000;
+ r.num = hashFontObject(&obj2);
}
fonts[i] = GfxFont::makeFont(xref, fontDict->getKey(i),
r, obj2.getDict());
@@ -2492,3 +2492,110 @@ GfxFont *GfxFontDict::lookup(char *tag) {
}
return nullptr;
}
+
+// FNV-1a hash
+class FNVHash {
+public:
+
+ FNVHash() {
+ h = 2166136261U;
+ }
+
+ void hash(char c) {
+ h ^= c & 0xff;
+ h *= 16777619;
+ }
+
+ void hash(char *p, int n) {
+ int i;
+ for (i = 0; i < n; ++i) {
+ hash(p[i]);
+ }
+ }
+
+ int get31() {
+ return (h ^ (h >> 31)) & 0x7fffffff;
+ }
+
+private:
+
+ Guint h;
+};
+
+int GfxFontDict::hashFontObject(Object *obj) {
+ FNVHash h;
+
+ hashFontObject1(obj, &h);
+ return h.get31();
+}
+
+void GfxFontDict::hashFontObject1(Object *obj, FNVHash *h) {
+ Object obj2;
+ GooString *s;
+ char *p;
+ double r;
+ int n, i;
+
+ switch (obj->getType()) {
+ case objBool:
+ h->hash('b');
+ h->hash(obj->getBool() ? 1 : 0);
+ break;
+ case objInt:
+ h->hash('i');
+ n = obj->getInt();
+ h->hash((char *)&n, sizeof(int));
+ break;
+ case objReal:
+ h->hash('r');
+ r = obj->getReal();
+ h->hash((char *)&r, sizeof(double));
+ break;
+ case objString:
+ h->hash('s');
+ s = obj->getString();
+ h->hash(s->getCString(), s->getLength());
+ break;
+ case objName:
+ h->hash('n');
+ p = obj->getName();
+ h->hash(p, (int)strlen(p));
+ break;
+ case objNull:
+ h->hash('z');
+ break;
+ case objArray:
+ h->hash('a');
+ n = obj->arrayGetLength();
+ h->hash((char *)&n, sizeof(int));
+ for (i = 0; i < n; ++i) {
+ obj2 = obj->arrayGetNF(i);
+ hashFontObject1(&obj2, h);
+ }
+ break;
+ case objDict:
+ h->hash('d');
+ n = obj->dictGetLength();
+ h->hash((char *)&n, sizeof(int));
+ for (i = 0; i < n; ++i) {
+ p = obj->dictGetKey(i);
+ h->hash(p, (int)strlen(p));
+ obj2 = obj->dictGetValNF(i);
+ hashFontObject1(&obj2, h);
+ }
+ break;
+ case objStream:
+ // this should never happen - streams must be indirect refs
+ break;
+ case objRef:
+ h->hash('f');
+ n = obj->getRefNum();
+ h->hash((char *)&n, sizeof(int));
+ n = obj->getRefGen();
+ h->hash((char *)&n, sizeof(int));
+ break;
+ default:
+ h->hash('u');
+ break;
+ }
+}
diff --git a/poppler/GfxFont.h b/poppler/GfxFont.h
index 00df389a..e082cdde 100644
--- a/poppler/GfxFont.h
+++ b/poppler/GfxFont.h
@@ -48,6 +48,7 @@ class FoFiTrueType;
class PSOutputDev;
struct GfxFontCIDWidths;
struct Base14FontMapEntry;
+class FNVHash;
//------------------------------------------------------------------------
// GfxFontType
@@ -458,6 +459,9 @@ public:
private:
+ int hashFontObject(Object *obj);
+ void hashFontObject1(Object *obj, FNVHash *h);
+
GfxFont **fonts; // list of fonts
int numFonts; // number of fonts
};
More information about the poppler
mailing list