def __init__(self, name, abr=''):
self.fName = name
self.fAbr = abr
+
+ def toCpp(self):
+ return '\"' + self.fName + '\"'
+
+class PdfString:
+ def __init__(self, value):
+ self.fValue = value
+
+ def toCpp(self):
+ return '\"' + self.fValue + '\"'
class PdfInteger:
def __init__(self, value):
self.fValue = value
+ def toCpp(self):
+ return str(self.fValue)
+
class PdfReal:
def __init__(self, value):
self.fValue = value
+ def toCpp(self):
+ return str(self.fValue)
+
class PdfString:
def __init__(self, value):
self.fValue = value
+ def toCpp(self):
+ return self.fValue
+
class PdfBoolean:
def __init__(self, value):
self.fValue = value
+ def toCpp(self):
+ return self.fValue
+
class PdfField:
def __init__(self, parent, name, abr):
self.fParent = parent
self.fDefault = ''
self.fType = ''
+ self.fCppName = ''
+ self.fCppType = ''
+ self.fCppReader = ''
+ self.fValidOptions = []
+ self.fHasMust = False
+ self.fMustBe = ''
def must(self, value):
- return self.fParent
+ self.fHasMust = True
+ self.fMustBe = value
+ return self
def default(self, value):
self.fDefault = value
return self
- def number(self):
+ def number(self, name):
self.fType = 'number'
+ self.fCppName = name
+ self.fCppType = 'double'
+ self.fCppReader = 'DoubleFromDictionary'
return self
- def integer(self):
+ def integer(self, name):
self.fType = 'integer'
+ self.fCppName = name
+ self.fCppType = 'long'
+ self.fCppReader = 'LongFromDictionary'
return self
- def real(self):
+ def real(self, name):
self.fType = 'real'
+ self.fCppName = name
+ self.fCppType = 'double'
+ self.fCppReader = 'DoubleFromDictionary'
return self
- def name(self):
+ def name(self, name):
self.fType = 'name'
+ self.fCppName = name
+ self.fCppType = 'std::string'
+ self.fCppReader = 'NameFromDictionary'
return self
- def string(self):
+ def string(self, name):
self.fType = 'string'
+ self.fCppName = name
+ self.fCppType = 'std::string'
+ self.fCppReader = 'StringFromDictionary'
return self
- def multiple(self, options):
- self.fType = 'multiple'
- self.fOptions = options
+ def multiple(self, validOptions):
+ self.fValidOptions = validOptions
return self
def done(self):
class PdfClassField:
def __init__(self, parent, required):
- self.fFields = []
- self.fIncludes = []
- self.fCC = []
+ #self.fProp = ''
self.fParent = parent
self.fRequired = required
- def hasField(self, name, abr=''):
- return PdfField(self, name, abr)
+ def field(self, name, abr=''):
+ self.fProp = PdfField(self, name, abr)
+ return self.fProp
def done(self):
return self.fParent
def __init__(self, name, base):
self.fFields = []
self.fIncludes = []
- self.fCC = []
+ self.fCCPublic = []
+ self.fCCPrivate = []
self.fName = name
self.fBase = base
self.fEnum = '!UNDEFINED'
self.fEnumEnd = '!UNDEFINED'
- def required(self):
+ def required(self, badDefault):
field = PdfClassField(self, True)
+ field.fBadDefault = badDefault
self.fFields.append(field)
return field
self.fIncludes.append(path)
return self
- def carbonCopy(self, cc):
- self.fCC.append(cc)
+ def carbonCopyPublic(self, cc):
+ self.fCCPublic.append(cc)
+ return self
+
+ def carbonCopyPrivate(self, cc):
+ self.fCCPrivate.append(cc)
return self
class PdfClassManager:
def __init__(self):
self.fClasses = {}
+ self.fClassesNamesInOrder = []
- def addClass(self, name, base=''):
- cls = PdfClass(name, base)
+ def addClass(self, name, base='Object'):
+ if name == 'Object':
+ cls = PdfClass(name, '')
+ else:
+ cls = PdfClass(name, base)
self.fClasses[name] = cls
+ self.fClassesNamesInOrder.append(name)
return cls
def longName(self, name):
if cnt != 0:
print(' ' + cls.fEnumEnd + ',')
+
+
+ def writeAsNull(self, cls, enumToCls):
+ print(' virtual SkPdf' + cls.fName +'* as' + cls.fName + '() {return NULL;}')
+ print(' virtual const SkPdf' + cls.fName +'* as' + cls.fName + '() const {return NULL;}')
+ print
+
+ cnt = 0
+ for sub in cls.fEnumSubclasses:
+ self.writeAsNull(enumToCls[cls.fEnumSubclasses[cnt]], enumToCls)
+ cnt = cnt + 1
+
+
+ def writeAsFoo(self, cls, enumToCls):
+ # TODO(edisonn): add a container, with sections, public, private, default, ...
+ # the end code will be grouped
+
+ # me
+ print('public:')
+ print(' virtual SkPdf' + cls.fName +'* as' + cls.fName + '() {return this;}')
+ print(' virtual const SkPdf' + cls.fName +'* as' + cls.fName + '() const {return this;}')
+ print
+
+ if cls.fName == 'Object':
+ cnt = 0
+ for sub in cls.fEnumSubclasses:
+ self.writeAsNull(enumToCls[cls.fEnumSubclasses[cnt]], enumToCls)
+ cnt = cnt + 1
+
+ if cls.fName != 'Object':
+ print('private:')
+ base = self.fClasses[cls.fBase]
+ cnt = 0
+ for sub in base.fEnumSubclasses:
+ if enumToCls[base.fEnumSubclasses[cnt]].fName != cls.fName:
+ self.writeAsNull(enumToCls[base.fEnumSubclasses[cnt]], enumToCls)
+ cnt = cnt + 1
+
+
def write(self):
# generate enum
for name in self.fClasses:
cls = self.fClasses[name]
enum = self.longName(name)
- cls.fEnum = 'k' + enum + '_PdfObjectType'
- cls.fEnumEnd = 'k' + enum + '__End_PdfObjectType'
+ cls.fEnum = 'k' + enum + '_SkPdfObjectType'
+ cls.fEnumEnd = 'k' + enum + '__End_SkPdfObjectType'
if cls.fBase != '':
self.fClasses[cls.fBase].fEnumSubclasses.append(cls.fEnum)
enumsRoot.sort()
+
+ # TODO(edisonn): move each .h in it's own file
+ # write imports
+
# write enums
- print('enum PdfObjectType {')
+ print('enum SkPdfObjectType {')
for enum in enumsRoot:
self.writeEnum(enum, enumToCls)
print('};')
+ print
+
+ # write forward class declaration
+ for name in self.fClassesNamesInOrder:
+ print('class SkPdf' + name + ';')
+ print
+
+ for name in self.fClassesNamesInOrder:
+ cls = self.fClasses[name]
+ enum = cls.fEnum
+
+ if cls.fBase == '':
+ print('class SkPdf' + cls.fName + ' {')
+ else:
+ print('class SkPdf' + cls.fName + ' : public SkPdf' + cls.fBase + ' {')
+
+ print('public:')
+ print(' virtual SkPdfObjectType getType() const { return ' + cls.fEnum + ';}')
+ if len(cls.fEnumSubclasses) == 0:
+ print(' virtual SkPdfObjectType getTypeEnd() const { return (SkPdfObjectType)(' + cls.fEnum + ' + 1);}')
+ else:
+ print(' virtual SkPdfObjectType getTypeEnd() const { return ' + cls.fEnumEnd + ';}')
+
+
+ self.writeAsFoo(cls, enumToCls)
+
+ print('public:')
+ for cc in cls.fCCPublic:
+ print(' ' + cc)
+
+ print('private:')
+ for cc in cls.fCCPrivate:
+ print(' ' + cc)
+
+ if cls.fBase == '':
+ print('protected:')
+ print(' const PdfMemDocument* fPodofoDoc;')
+ print(' const PdfObject* fPodofoObj;')
+ print
+ print('public:')
+ print(' SkPdf' + cls.fName + '(const PdfMemDocument* podofoDoc, const PdfObject* podofoObj) : fPodofoDoc(podofoDoc), fPodofoObj(podofoObj) {}')
+ print(' const PdfObject* podofo() const { return fPodofoObj;}')
+ else:
+ print('public:')
+ print(' SkPdf' + cls.fName + '(const PdfMemDocument* podofoDoc, const PdfObject* podofoObj) : SkPdf' + cls.fBase + '(podofoDoc, podofoObj) {}')
+
+ #check required fieds, also, there should be an internal_valid() manually wrote for complex
+ # situations
+ # right now valid return true
+ print(' virtual bool valid() const {return true;}')
+
+ for field in cls.fFields:
+ prop = field.fProp
+ if prop.fCppName != '':
+ print(' ' + prop.fCppType + ' ' + prop.fCppName + '() const {')
+ print(' ' + prop.fCppType + ' ret;')
+ print(' if (' + prop.fCppReader + '(fPodofoDoc, fPodofoObj->GetDictionary(), \"' + prop.fName + '\", \"' + prop.fAbr + '\", &ret)) return ret;')
+ if field.fRequired == False:
+ print(' return ' + prop.fDefault.toCpp() + ';');
+ if field.fRequired == True:
+ print(' // TODO(edisonn): warn about missing required field, assert for known good pdfs')
+ print(' return ' + field.fBadDefault + ';');
+ print(' }')
+ print
+
+ print('};')
+ print
+ print
+
+
+
+ # generate constructor when knowing the type
+ # later, p2, generate constructor when not knowing the type - very similar with parsing?
- # generate each class
# generate parser
+
+ # TODO(edisonn): fast recognition based on must attributes.
+ print('class PodofoMapper {')
+ print('public:')
+ for name in self.fClassesNamesInOrder:
+ cls = self.fClasses[name]
+
+ print(' static bool map' + name + '(const PdfMemDocument& podofoDoc, const PdfObject& podofoObj, SkPdfObject** out) {')
+ print(' if (!isA' + name + '(podofoDoc, podofoObj)) return false;')
+ print
+
+ for sub in cls.fEnumSubclasses:
+ print(' if (map' + enumToCls[sub].fName + '(podofoDoc, podofoObj, out)) return true;')
+
+ print
+
+ print(' *out = new SkPdf' + name + '(&podofoDoc, &podofoObj);')
+ print(' return true;')
+ print(' }')
+ print
+
+ for name in self.fClassesNamesInOrder:
+ cls = self.fClasses[name]
+
+ print(' static bool isA' + name + '(const PdfMemDocument& podofoDoc, const PdfObject& podofoObj) {')
+
+ cntMust = 0
+ for field in cls.fFields:
+ prop = field.fProp
+ if prop.fHasMust:
+ cntMust = cntMust + 1
+ print(' ' + prop.fCppType + ' ' + prop.fCppName + ';')
+ print(' if (!' + prop.fCppReader + '(&podofoDoc, podofoObj.GetDictionary(), \"' + prop.fName + '\", \"' + prop.fAbr + '\", &' + prop.fCppName + ')) return false;')
+ print(' if (' + prop.fCppName + ' != ' + prop.fMustBe.toCpp() + ') return false;')
+ print
+
+ # hack, we only care about dictionaries now, so ret tru only if there is a match
+ if cntMust != 0 or name == 'Object' or name == 'Dictionary':
+ print(' return true;')
+ else:
+ print(' return false;')
+
+ print(' }')
+ print
+
+ print('};')
+ print
+
return
def generateCode():
all.addClass('Array')
all.addClass('Dictionary')
- all.addClass('XObject', 'Dictionary').required().hasField('/Type').must('/XObject')
+ all.addClass('XObject', 'Dictionary').required('""').field('Type').must(PdfName('XObject')).name('t')
- all.addClass('Image', 'XObject').required().hasField('/Type').must('/XObject').done()\
- .required().hasField('/Subtype').must('/Image').done()\
- .required().hasField('/Width', '/W').integer().done().done()\
- .required().hasField('/Height', '/H').integer().done().done()\
- .required().hasField('/ColorSpace').multiple([PdfName('/DeviceRGB', '/RGB'), PdfName('/DeviceGray', '/Gray')])\
+ all.addClass('Image', 'XObject').required('""').field('Type').must(PdfName('XObject')).name('t').done()\
+ .done()\
+ .required('""').field('Subtype').must(PdfName('Image')).name('s').done()\
+ .done()\
+ .required('-1').field('Width', 'W').integer('w').done()\
+ .done()\
+ .required('-1').field('Height', 'H').integer('h').done()\
+ .done()\
+ .required('""').field('ColorSpace').name('cs').multiple([PdfName('/DeviceRGB', '/RGB'), PdfName('/DeviceGray', '/Gray')]).done()\
+ .done()\
+ .optional().field('BitsPerComponent', 'BPC').integer('bpc').multiple([PdfInteger(1), PdfInteger(2), PdfInteger(4), PdfInteger(8)])\
+ .default(PdfInteger(1)).done()\
.done()\
- .done()\
- .optional().hasField('/BitsPerComponent', '/BPC').multiple([PdfInteger(1), PdfInteger(2), PdfInteger(4), PdfInteger(8)])\
- .default(PdfInteger(1))\
- .done().done()\
- .carbonCopy('SkBitmap bitmap;')
-
- all.addClass('Form', 'XObject').required().hasField('/Type').must('/XObject').done()\
- .required().hasField('/Subtype').must('/Form').done()
+ .carbonCopyPrivate('SkBitmap bitmap;')
+
+ all.addClass('Form', 'XObject').required('""').field('Type').must(PdfName('XObject')).name('t').done()\
+ .done()\
+ .required('""').field('Subtype').must(PdfName('Form')).name('s').done()\
+ .done()\
+ .carbonCopyPublic('void test() {}')
all.write()
#include <stack>
#include "podofo.h"
+using namespace PoDoFo;
+
+bool LongFromDictionary(const PdfMemDocument* pdfDoc,
+ const PdfDictionary& dict,
+ const char* key,
+ const char* abr,
+ long* data);
+
+bool BoolFromDictionary(const PdfMemDocument* pdfDoc,
+ const PdfDictionary& dict,
+ const char* key,
+ const char* abr,
+ bool* data);
+
+bool NameFromDictionary(const PdfMemDocument* pdfDoc,
+ const PdfDictionary& dict,
+ const char* key,
+ const char* abr,
+ std::string* data);
+
+
+
+#include "pdf_auto_gen.h"
/*
* TODO(edisonn): ASAP so skp -> pdf -> png looks greap
* - load font for youtube.pdf
*/
-//#define PDF_TRACE
+#define PDF_TRACE
//#define PDF_TRACE_DIFF_IN_PNG
//#define PDF_DEBUG_NO_CLIPING
//#define PDF_DEBUG_NO_PAGE_CLIPING
}
}
-PdfObject* resolveReferenceObject(PdfMemDocument* pdfDoc,
- PdfObject* obj,
- bool resolveOneElementArrays = false) {
+const PdfObject* resolveReferenceObject(const PdfMemDocument* pdfDoc,
+ const PdfObject* obj,
+ bool resolveOneElementArrays = false) {
while (obj && (obj->IsReference() || (resolveOneElementArrays &&
obj->IsArray() &&
obj->GetArray().GetSize() == 1))) {
double fWordSpace;
double fCharSpace;
- PdfObject* fObjectWithResources;
+ const PdfObject* fObjectWithResources;
SkBitmap fSMask;
if (fCurFont->GetObject()->IsDictionary() && fCurFont->GetObject()->GetDictionary().HasKey(PdfName("ToUnicode"))) {
PdfCMapEncoding* enc = new PdfCMapEncoding(
fCurFont->GetObject(),
- resolveReferenceObject(pdfContext->fPdfDoc,
+ (PdfObject*)resolveReferenceObject(pdfContext->fPdfDoc,
fCurFont->GetObject()->GetDictionary().GetKey(PdfName("ToUnicode"))),
PdfCMapEncoding::eBaseEncoding_Identity); // todo, read the base encoding
gFontsFixed[fCurFont] = enc;
// TODO(edisonn): deal with synonyms (/BPC == /BitsPerComponent), here or in GetKey?
// Always pass long form in key, and have a map of long -> short key
-bool LongFromDictionary(PdfContext* pdfContext,
- PdfDictionary& dict,
+bool LongFromDictionary(const PdfMemDocument* pdfDoc,
+ const PdfDictionary& dict,
const char* key,
long* data) {
- PdfObject* value = resolveReferenceObject(pdfContext->fPdfDoc,
- dict.GetKey(PdfName(key)));
+ const PdfObject* value = resolveReferenceObject(pdfDoc,
+ dict.GetKey(PdfName(key)));
if (value == NULL || !value->IsNumber()) {
return false;
return true;
}
-bool BoolFromDictionary(PdfContext* pdfContext,
- PdfDictionary& dict,
+bool LongFromDictionary(const PdfMemDocument* pdfDoc,
+ const PdfDictionary& dict,
+ const char* key,
+ const char* abr,
+ long* data) {
+ if (LongFromDictionary(pdfDoc, dict, key, data)) return true;
+ if (abr == NULL || *abr == '\0') return false;
+ return LongFromDictionary(pdfDoc, dict, abr, data);
+}
+
+bool BoolFromDictionary(const PdfMemDocument* pdfDoc,
+ const PdfDictionary& dict,
const char* key,
bool* data) {
- PdfObject* value = resolveReferenceObject(pdfContext->fPdfDoc,
- dict.GetKey(PdfName(key)));
+ const PdfObject* value = resolveReferenceObject(pdfDoc,
+ dict.GetKey(PdfName(key)));
if (value == NULL || !value->IsBool()) {
return false;
return true;
}
-bool NameFromDictionary(PdfContext* pdfContext,
- PdfDictionary& dict,
+bool BoolFromDictionary(const PdfMemDocument* pdfDoc,
+ const PdfDictionary& dict,
+ const char* key,
+ const char* abr,
+ bool* data) {
+ if (BoolFromDictionary(pdfDoc, dict, key, data)) return true;
+ if (abr == NULL || *abr == '\0') return false;
+ return BoolFromDictionary(pdfDoc, dict, abr, data);
+}
+
+bool NameFromDictionary(const PdfMemDocument* pdfDoc,
+ const PdfDictionary& dict,
const char* key,
std::string* data) {
- PdfObject* value = resolveReferenceObject(pdfContext->fPdfDoc,
- dict.GetKey(PdfName(key)),
- true);
+ const PdfObject* value = resolveReferenceObject(pdfDoc,
+ dict.GetKey(PdfName(key)),
+ true);
if (value == NULL || !value->IsName()) {
return false;
}
return true;
}
+bool NameFromDictionary(const PdfMemDocument* pdfDoc,
+ const PdfDictionary& dict,
+ const char* key,
+ const char* abr,
+ std::string* data) {
+ if (NameFromDictionary(pdfDoc, dict, key, data)) return true;
+ if (abr == NULL || *abr == '\0') return false;
+ return NameFromDictionary(pdfDoc, dict, abr, data);
+}
+
// TODO(edisonn): perf!!!
static SkColorTable* getGrayColortable() {
// this functions returns the image, it does not look at the smask.
-SkBitmap getImageFromObject(PdfContext* pdfContext, PdfObject& obj, bool transparencyMask) {
+SkBitmap getImageFromObject(PdfContext* pdfContext, const SkPdfImage* image, bool transparencyMask) {
+ if (image == NULL || !image->valid()) {
+ // TODO(edisonn): report warning to be used in testing.
+ return SkBitmap();
+ }
+
+ // TODO (edisonn): Fast Jpeg(DCTDecode) draw, or fast PNG(FlateDecode) draw ...
+// PdfObject* value = resolveReferenceObject(pdfContext->fPdfDoc,
+// obj.GetDictionary().GetKey(PdfName("Filter")));
+// if (value && value->IsArray() && value->GetArray().GetSize() == 1) {
+// value = resolveReferenceObject(pdfContext->fPdfDoc,
+// &value->GetArray()[0]);
+// }
+// if (value && value->IsName() && value->GetName().GetName() == "DCTDecode") {
+// SkStream stream = SkStream::
+// SkImageDecoder::Factory()
+// }
+
+ long bpc = image->bpc();
+ long width = image->w();
+ long height = image->h();
+ std::string colorSpace = image->cs();
+
+/*
+ bool imageMask = image->imageMask();
+
+ if (imageMask) {
+ if (bpc != 0 && bpc != 1) {
+ // TODO(edisonn): report warning to be used in testing.
+ return SkBitmap();
+ }
+ bpc = 1;
+ }
+*/
+
+ const PdfObject* obj = image->podofo();
+
+ char* uncompressedStream = NULL;
+ pdf_long uncompressedStreamLength = 0;
+
+ PdfResult ret = kPartial_PdfResult;
+ // TODO(edisonn): get rid of try/catch exceptions! We should not throw on user data!
+ try {
+ obj->GetStream()->GetFilteredCopy(&uncompressedStream, &uncompressedStreamLength);
+ } catch (PdfError& e) {
+ // TODO(edisonn): report warning to be used in testing.
+ return SkBitmap();
+ }
+
+ int bytesPerLine = uncompressedStreamLength / height;
+#ifdef PDF_TRACE
+ if (uncompressedStreamLength % height != 0) {
+ printf("Warning uncompressedStreamLength % height != 0 !!!\n");
+ }
+#endif
+
+ SkBitmap bitmap = transferImageStreamToBitmap(
+ (unsigned char*)uncompressedStream, uncompressedStreamLength,
+ width, height, bytesPerLine,
+ bpc, colorSpace,
+ transparencyMask);
+
+ free(uncompressedStream);
+
+ return bitmap;
+}
+
+SkBitmap getImageFromObjectOld(PdfContext* pdfContext, const PdfObject& obj, bool transparencyMask) {
if (!obj.HasStream() || obj.GetStream() == NULL || obj.GetStream()->GetLength() == 0 ||
!obj.IsDictionary()) {
// TODO(edisonn): report warning to be used in testing.
return SkBitmap();
}
- PdfObject* value = resolveReferenceObject(pdfContext->fPdfDoc,
+ const PdfObject* value = resolveReferenceObject(pdfContext->fPdfDoc,
obj.GetDictionary().GetKey(PdfName("Filter")));
if (value && value->IsArray() && value->GetArray().GetSize() == 1) {
// translate
long bpc = 0;
- LongFromDictionary(pdfContext, obj.GetDictionary(), "BitsPerComponent", &bpc);
+ LongFromDictionary(pdfContext->fPdfDoc, obj.GetDictionary(), "BitsPerComponent", "BPC", &bpc);
bool imageMask = false;
- BoolFromDictionary(pdfContext, obj.GetDictionary(), "ImageMask", &imageMask);
+ BoolFromDictionary(pdfContext->fPdfDoc, obj.GetDictionary(), "ImageMask", "", &imageMask);
if (imageMask) {
if (bpc != 0 && bpc != 1) {
}
long width;
- if (!LongFromDictionary(pdfContext, obj.GetDictionary(), "Width", &width)) {
+ if (!LongFromDictionary(pdfContext->fPdfDoc, obj.GetDictionary(), "Width", &width)) {
// TODO(edisonn): report warning to be used in testing.
return SkBitmap();
}
long height;
- if (!LongFromDictionary(pdfContext, obj.GetDictionary(), "Height", &height)) {
+ if (!LongFromDictionary(pdfContext->fPdfDoc, obj.GetDictionary(), "Height", &height)) {
// TODO(edisonn): report warning to be used in testing.
return SkBitmap();
}
std::string colorSpace; // TODO(edisonn): load others than names, for more complicated
- if (!NameFromDictionary(pdfContext, obj.GetDictionary(), "ColorSpace", &colorSpace)) {
+ if (!NameFromDictionary(pdfContext->fPdfDoc, obj.GetDictionary(), "ColorSpace", &colorSpace)) {
// TODO(edisonn): report warning to be used in testing.
return SkBitmap();
}
return bitmap;
}
-SkBitmap getSmaskFromObject(PdfContext* pdfContext, PdfObject& obj) {
- PdfObject* sMask = resolveReferenceObject(pdfContext->fPdfDoc,
+SkBitmap getSmaskFromObject(PdfContext* pdfContext, const SkPdfImage* obj) {
+ const PdfObject* sMask = resolveReferenceObject(pdfContext->fPdfDoc,
+ obj->podofo()->GetDictionary().GetKey(PdfName("SMask")));
+
+#ifdef PDF_TRACE
+ std::string str;
+ if (sMask) {
+ sMask->ToString(str);
+ printf("/SMask of /Subtype /Image: %s\n", str.c_str());
+ }
+#endif
+
+ if (sMask) {
+ SkPdfImage skxobjmask(pdfContext->fPdfDoc, sMask);
+ return getImageFromObject(pdfContext, &skxobjmask, true);
+ }
+
+ // TODO(edisonn): implement GS SMask. Default to empty right now.
+ return pdfContext->fGraphicsState.fSMask;
+}
+
+SkBitmap getSmaskFromObjectOld(PdfContext* pdfContext, const PdfObject& obj) {
+ const PdfObject* sMask = resolveReferenceObject(pdfContext->fPdfDoc,
obj.GetDictionary().GetKey(PdfName("SMask")));
#ifdef PDF_TRACE
#endif
if (sMask) {
- return getImageFromObject(pdfContext, *sMask, true);
+ return getImageFromObjectOld(pdfContext, *sMask, true);
}
// TODO(edisonn): implement GS SMask. Default to empty right now.
return pdfContext->fGraphicsState.fSMask;
}
-PdfResult doXObject_Image(PdfContext* pdfContext, SkCanvas* canvas, PdfObject& obj) {
+
+PdfResult doXObject_Image(PdfContext* pdfContext, SkCanvas* canvas, const SkPdfImage* skpdfimage) {
+ if (skpdfimage == NULL || !skpdfimage->valid()) {
+ return kIgnoreError_PdfResult;
+ }
+
+ SkBitmap image = getImageFromObject(pdfContext, skpdfimage, false);
+ SkBitmap sMask = getSmaskFromObject(pdfContext, skpdfimage);
+
+ canvas->save();
+ canvas->setMatrix(pdfContext->fGraphicsState.fMatrix);
+ SkRect dst = SkRect::MakeXYWH(SkDoubleToScalar(0.0), SkDoubleToScalar(0.0), SkDoubleToScalar(1.0), SkDoubleToScalar(1.0));
+
+ if (sMask.empty()) {
+ canvas->drawBitmapRect(image, dst, NULL);
+ } else {
+ canvas->saveLayer(&dst, NULL);
+ canvas->drawBitmapRect(image, dst, NULL);
+ SkPaint xfer;
+ xfer.setXfermodeMode(SkXfermode::kSrcOut_Mode); // SkXfermode::kSdtOut_Mode
+ canvas->drawBitmapRect(sMask, dst, &xfer);
+ canvas->restore();
+ }
+
+ canvas->restore();
+
+ return kPartial_PdfResult;
+}
+
+PdfResult doXObject_ImageOld(PdfContext* pdfContext, SkCanvas* canvas, const PdfObject& obj) {
if (!obj.HasStream() || obj.GetStream() == NULL || obj.GetStream()->GetLength() == 0 ||
!obj.IsDictionary()) {
return kIgnoreError_PdfResult;
}
- SkBitmap image = getImageFromObject(pdfContext, obj, false);
- SkBitmap sMask = getSmaskFromObject(pdfContext, obj);
+ SkBitmap image = getImageFromObjectOld(pdfContext, obj, false);
+ SkBitmap sMask = getSmaskFromObjectOld(pdfContext, obj);
canvas->save();
canvas->setMatrix(pdfContext->fGraphicsState.fMatrix);
return kPartial_PdfResult;
}
-PdfResult doXObject_ImageOld(PdfContext* pdfContext, SkCanvas* canvas, PdfObject& obj) {
+
+PdfResult doXObject_ImageOld2(PdfContext* pdfContext, SkCanvas* canvas, const PdfObject& obj) {
if (!obj.HasStream() || obj.GetStream() == NULL || obj.GetStream()->GetLength() == 0 ||
!obj.IsDictionary()) {
return kIgnoreError_PdfResult;
}
- PdfObject* sMask = resolveReferenceObject(pdfContext->fPdfDoc,
+ const PdfObject* sMask = resolveReferenceObject(pdfContext->fPdfDoc,
obj.GetDictionary().GetKey(PdfName("SMask")));
// TODO(edisonn): else get smask from graphi state
// TODO(edisonn): add utility, SkBitmap loadBitmap(PdfObject& obj, bool no_smask);
}
#endif
+/*
+ // TODO (edisonn): Fast Jpeg(DCTDecode) draw, or fast PNG(FlateDecode) draw ...
PdfObject* value = resolveReferenceObject(pdfContext->fPdfDoc,
obj.GetDictionary().GetKey(PdfName("Filter")));
&value->GetArray()[0]);
}
- // TODO (edisonn): Fast Jpeg(DCTDecode) draw, or fast PNG(FlateDecode) draw ...
-// if (value && value->IsName() && value->GetName().GetName() == "DCTDecode") {
-// SkStream stream = SkStream::
-// SkImageDecoder::Factory()
-// }
-
+ if (value && value->IsName() && value->GetName().GetName() == "DCTDecode") {
+ SkStream stream = SkStream::
+ SkImageDecoder::Factory()
+ }
+*/
// Get color space
// trasnlate
long bpc = 0;
- LongFromDictionary(pdfContext, obj.GetDictionary(), "BitsPerComponent", &bpc);
+ LongFromDictionary(pdfContext->fPdfDoc, obj.GetDictionary(), "BitsPerComponent", "BPC", &bpc);
bool imageMask = false;
- BoolFromDictionary(pdfContext, obj.GetDictionary(), "ImageMask", &imageMask);
+ BoolFromDictionary(pdfContext->fPdfDoc, obj.GetDictionary(), "ImageMask", "", &imageMask);
if (imageMask) {
if (bpc != 0 && bpc != 1) {
}
long width;
- if (!LongFromDictionary(pdfContext, obj.GetDictionary(), "Width", &width)) {
+ if (!LongFromDictionary(pdfContext->fPdfDoc, obj.GetDictionary(), "Width", "W", &width)) {
return kIgnoreError_PdfResult;
}
long height;
- if (!LongFromDictionary(pdfContext, obj.GetDictionary(), "Height", &height)) {
+ if (!LongFromDictionary(pdfContext->fPdfDoc, obj.GetDictionary(), "Height", "H", &height)) {
return kIgnoreError_PdfResult;
}
std::string colorSpace; // TODO(edisonn): load others than names, for more complicated
- if (!NameFromDictionary(pdfContext, obj.GetDictionary(), "ColorSpace", &colorSpace)) {
+ if (!NameFromDictionary(pdfContext->fPdfDoc, obj.GetDictionary(), "ColorSpace", "", &colorSpace)) {
return kIgnoreError_PdfResult;
}
}
bool SkMatrixFromDictionary(PdfContext* pdfContext,
- PdfDictionary& dict,
+ const PdfDictionary& dict,
const char* key,
SkMatrix* matrix) {
- PdfObject* value = resolveReferenceObject(pdfContext->fPdfDoc,
+ const PdfObject* value = resolveReferenceObject(pdfContext->fPdfDoc,
dict.GetKey(PdfName(key)));
if (value == NULL || !value->IsArray()) {
double array[6];
for (int i = 0; i < 6; i++) {
- PdfObject* elem = resolveReferenceObject(pdfContext->fPdfDoc, &value->GetArray()[i]);
+ const PdfObject* elem = resolveReferenceObject(pdfContext->fPdfDoc, &value->GetArray()[i]);
if (elem == NULL || (!elem->IsReal() && !elem->IsNumber())) {
return false;
}
}
bool SkRectFromDictionary(PdfContext* pdfContext,
- PdfDictionary& dict,
+ const PdfDictionary& dict,
const char* key,
SkRect* rect) {
- PdfObject* value = resolveReferenceObject(pdfContext->fPdfDoc,
+ const PdfObject* value = resolveReferenceObject(pdfContext->fPdfDoc,
dict.GetKey(PdfName(key)));
if (value == NULL || !value->IsArray()) {
double array[4];
for (int i = 0; i < 4; i++) {
- PdfObject* elem = resolveReferenceObject(pdfContext->fPdfDoc, &value->GetArray()[i]);
+ const PdfObject* elem = resolveReferenceObject(pdfContext->fPdfDoc, &value->GetArray()[i]);
if (elem == NULL || (!elem->IsReal() && !elem->IsNumber())) {
return false;
}
return true;
}
-PdfResult doXObject_Form(PdfContext* pdfContext, SkCanvas* canvas, PdfObject& obj) {
+PdfResult doXObject_Form(PdfContext* pdfContext, SkCanvas* canvas, const PdfObject& obj) {
if (!obj.HasStream() || obj.GetStream() == NULL || obj.GetStream()->GetLength() == 0) {
return kOK_PdfResult;
}
return ret;
}
-PdfResult doXObject_PS(PdfContext* pdfContext, SkCanvas* canvas, PdfObject& obj) {
+PdfResult doXObject_PS(PdfContext* pdfContext, SkCanvas* canvas, const PdfObject& obj) {
return kNYI_PdfResult;
}
// TODO(edisonn): faster, have the property on the PdfObject itself.
-std::set<PdfObject*> gInRendering;
+std::set<const PdfObject*> gInRendering;
class CheckRecursiveRendering {
- PdfObject& fObj;
+ const PdfObject& fObj;
public:
- CheckRecursiveRendering(PdfObject& obj) : fObj(obj) {
+ CheckRecursiveRendering(const PdfObject& obj) : fObj(obj) {
gInRendering.insert(&obj);
}
gInRendering.erase(&fObj);
}
- static bool IsInRendering(PdfObject& obj) {
+ static bool IsInRendering(const PdfObject& obj) {
return gInRendering.find(&obj) != gInRendering.end();
}
};
-PdfResult doXObject(PdfContext* pdfContext, SkCanvas* canvas, PdfObject& obj) {
+PdfResult doXObject(PdfContext* pdfContext, SkCanvas* canvas, const PdfObject& obj) {
+ if (CheckRecursiveRendering::IsInRendering(obj)) {
+ // Oops, corrupt PDF!
+ return kIgnoreError_PdfResult;
+ }
+
+ CheckRecursiveRendering checkRecursion(obj);
+
+ // TODO(edisonn): check type
+ SkPdfObject* skobj = NULL;
+ if (!PodofoMapper::mapObject(*pdfContext->fPdfDoc, obj, &skobj)) return kIgnoreError_PdfResult;
+
+ if (!skobj || !skobj->valid()) return kIgnoreError_PdfResult;
+
+ PdfResult ret = kIgnoreError_PdfResult;
+ switch (skobj->getType())
+ {
+ case kObjectDictionaryXObjectImage_SkPdfObjectType:
+ ret = doXObject_Image(pdfContext, canvas, skobj->asImage());
+ //case kObjectDictionaryXObjectForm_SkPdfObjectType:
+ //return doXObject_Form(skxobj.asForm());
+ //case kObjectDictionaryXObjectPS_SkPdfObjectType:
+ //return doXObject_PS(skxobj.asPS());
+ }
+
+ delete skobj;
+ return ret;
+}
+
+PdfResult doXObjectOld(PdfContext* pdfContext, SkCanvas* canvas, const PdfObject& obj) {
if (CheckRecursiveRendering::IsInRendering(obj)) {
// Oops, corrupt PDF!
return kIgnoreError_PdfResult;
return kIgnoreError_PdfResult;
}
- PdfObject* type = resolveReferenceObject(pdfContext->fPdfDoc,
+ const PdfObject* type = resolveReferenceObject(pdfContext->fPdfDoc,
obj.GetDictionary().GetKey(PdfName("Type")));
if (type == NULL || !type->IsName()) {
return kIgnoreError_PdfResult;
}
- PdfObject* subtype =
+ const PdfObject* subtype =
resolveReferenceObject(pdfContext->fPdfDoc,
obj.GetDictionary().GetKey(PdfName("Subtype")));
}
if (subtype->GetName().GetName() == "Image") {
- return doXObject_Image(pdfContext, canvas, obj);
+ return doXObject_ImageOld(pdfContext, canvas, obj);
} else if (subtype->GetName().GetName() == "Form") {
return doXObject_Form(pdfContext, canvas, obj);
} else if (subtype->GetName().GetName() == "PS") {
PdfResult PdfOp_gs(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
PdfName name = pdfContext->fVarStack.top().GetName(); pdfContext->fVarStack.pop();
- PdfDictionary& pageDict = pdfContext->fGraphicsState.fObjectWithResources->GetDictionary();
- PdfObject* resources = resolveReferenceObject(pdfContext->fPdfDoc,
+ const PdfDictionary& pageDict = pdfContext->fGraphicsState.fObjectWithResources->GetDictionary();
+ const PdfObject* resources = resolveReferenceObject(pdfContext->fPdfDoc,
pageDict.GetKey("Resources"));
if (resources == NULL) {
return kIgnoreError_PdfResult;
}
- PdfDictionary& resourceDict = resources->GetDictionary();
+ const PdfDictionary& resourceDict = resources->GetDictionary();
//Next, get the ExtGState Dictionary from the Resource Dictionary:
- PdfObject* extGStateDictionary = resolveReferenceObject(pdfContext->fPdfDoc,
+ const PdfObject* extGStateDictionary = resolveReferenceObject(pdfContext->fPdfDoc,
resourceDict.GetKey("ExtGState"));
if (extGStateDictionary == NULL) {
return kIgnoreError_PdfResult;
}
- PdfObject* value =
+ const PdfObject* value =
resolveReferenceObject(pdfContext->fPdfDoc,
extGStateDictionary->GetDictionary().GetKey(name));
PdfResult PdfOp_Do(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
PdfName name = pdfContext->fVarStack.top().GetName(); pdfContext->fVarStack.pop();
- PdfDictionary& pageDict = pdfContext->fGraphicsState.fObjectWithResources->GetDictionary();
- PdfObject* resources = resolveReferenceObject(pdfContext->fPdfDoc,
+ const PdfDictionary& pageDict = pdfContext->fGraphicsState.fObjectWithResources->GetDictionary();
+ const PdfObject* resources = resolveReferenceObject(pdfContext->fPdfDoc,
pageDict.GetKey("Resources"));
if (resources == NULL) {
return kIgnoreError_PdfResult;
}
- PdfDictionary& resourceDict = resources->GetDictionary();
+ const PdfDictionary& resourceDict = resources->GetDictionary();
//Next, get the XObject Dictionary from the Resource Dictionary:
- PdfObject* xObjectDictionary = resolveReferenceObject(pdfContext->fPdfDoc,
+ const PdfObject* xObjectDictionary = resolveReferenceObject(pdfContext->fPdfDoc,
resourceDict.GetKey("XObject"));
if (xObjectDictionary == NULL) {
return kIgnoreError_PdfResult;
}
- PdfObject* value =
+ const PdfObject* value =
resolveReferenceObject(pdfContext->fPdfDoc,
xObjectDictionary->GetDictionary().GetKey(name));