Code generator for dinamic generation of podofo wrappers
Review URL: https://codereview.chromium.org/16838002 git-svn-id: http://skia.googlecode.com/svn/trunk@9544 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
bd4af3a9a6
commit
af3daa01f6
@ -5,22 +5,44 @@ class PdfName:
|
|||||||
self.fName = name
|
self.fName = name
|
||||||
self.fAbr = abr
|
self.fAbr = abr
|
||||||
|
|
||||||
class PdfInteger:
|
def toCpp(self):
|
||||||
def __init__(self, value):
|
return '\"' + self.fName + '\"'
|
||||||
self.fValue = value
|
|
||||||
|
|
||||||
class PdfReal:
|
|
||||||
def __init__(self, value):
|
|
||||||
self.fValue = value
|
|
||||||
|
|
||||||
class PdfString:
|
class PdfString:
|
||||||
def __init__(self, value):
|
def __init__(self, value):
|
||||||
self.fValue = 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:
|
class PdfBoolean:
|
||||||
def __init__(self, value):
|
def __init__(self, value):
|
||||||
self.fValue = value
|
self.fValue = value
|
||||||
|
|
||||||
|
def toCpp(self):
|
||||||
|
return self.fValue
|
||||||
|
|
||||||
class PdfField:
|
class PdfField:
|
||||||
def __init__(self, parent, name, abr):
|
def __init__(self, parent, name, abr):
|
||||||
self.fParent = parent
|
self.fParent = parent
|
||||||
@ -29,37 +51,59 @@ class PdfField:
|
|||||||
|
|
||||||
self.fDefault = ''
|
self.fDefault = ''
|
||||||
self.fType = ''
|
self.fType = ''
|
||||||
|
self.fCppName = ''
|
||||||
|
self.fCppType = ''
|
||||||
|
self.fCppReader = ''
|
||||||
|
self.fValidOptions = []
|
||||||
|
self.fHasMust = False
|
||||||
|
self.fMustBe = ''
|
||||||
|
|
||||||
def must(self, value):
|
def must(self, value):
|
||||||
return self.fParent
|
self.fHasMust = True
|
||||||
|
self.fMustBe = value
|
||||||
|
return self
|
||||||
|
|
||||||
def default(self, value):
|
def default(self, value):
|
||||||
self.fDefault = value
|
self.fDefault = value
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def number(self):
|
def number(self, name):
|
||||||
self.fType = 'number'
|
self.fType = 'number'
|
||||||
|
self.fCppName = name
|
||||||
|
self.fCppType = 'double'
|
||||||
|
self.fCppReader = 'DoubleFromDictionary'
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def integer(self):
|
def integer(self, name):
|
||||||
self.fType = 'integer'
|
self.fType = 'integer'
|
||||||
|
self.fCppName = name
|
||||||
|
self.fCppType = 'long'
|
||||||
|
self.fCppReader = 'LongFromDictionary'
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def real(self):
|
def real(self, name):
|
||||||
self.fType = 'real'
|
self.fType = 'real'
|
||||||
|
self.fCppName = name
|
||||||
|
self.fCppType = 'double'
|
||||||
|
self.fCppReader = 'DoubleFromDictionary'
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def name(self):
|
def name(self, name):
|
||||||
self.fType = 'name'
|
self.fType = 'name'
|
||||||
|
self.fCppName = name
|
||||||
|
self.fCppType = 'std::string'
|
||||||
|
self.fCppReader = 'NameFromDictionary'
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def string(self):
|
def string(self, name):
|
||||||
self.fType = 'string'
|
self.fType = 'string'
|
||||||
|
self.fCppName = name
|
||||||
|
self.fCppType = 'std::string'
|
||||||
|
self.fCppReader = 'StringFromDictionary'
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def multiple(self, options):
|
def multiple(self, validOptions):
|
||||||
self.fType = 'multiple'
|
self.fValidOptions = validOptions
|
||||||
self.fOptions = options
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def done(self):
|
def done(self):
|
||||||
@ -68,14 +112,13 @@ class PdfField:
|
|||||||
|
|
||||||
class PdfClassField:
|
class PdfClassField:
|
||||||
def __init__(self, parent, required):
|
def __init__(self, parent, required):
|
||||||
self.fFields = []
|
#self.fProp = ''
|
||||||
self.fIncludes = []
|
|
||||||
self.fCC = []
|
|
||||||
self.fParent = parent
|
self.fParent = parent
|
||||||
self.fRequired = required
|
self.fRequired = required
|
||||||
|
|
||||||
def hasField(self, name, abr=''):
|
def field(self, name, abr=''):
|
||||||
return PdfField(self, name, abr)
|
self.fProp = PdfField(self, name, abr)
|
||||||
|
return self.fProp
|
||||||
|
|
||||||
def done(self):
|
def done(self):
|
||||||
return self.fParent
|
return self.fParent
|
||||||
@ -84,7 +127,8 @@ class PdfClass:
|
|||||||
def __init__(self, name, base):
|
def __init__(self, name, base):
|
||||||
self.fFields = []
|
self.fFields = []
|
||||||
self.fIncludes = []
|
self.fIncludes = []
|
||||||
self.fCC = []
|
self.fCCPublic = []
|
||||||
|
self.fCCPrivate = []
|
||||||
self.fName = name
|
self.fName = name
|
||||||
self.fBase = base
|
self.fBase = base
|
||||||
|
|
||||||
@ -93,8 +137,9 @@ class PdfClass:
|
|||||||
self.fEnum = '!UNDEFINED'
|
self.fEnum = '!UNDEFINED'
|
||||||
self.fEnumEnd = '!UNDEFINED'
|
self.fEnumEnd = '!UNDEFINED'
|
||||||
|
|
||||||
def required(self):
|
def required(self, badDefault):
|
||||||
field = PdfClassField(self, True)
|
field = PdfClassField(self, True)
|
||||||
|
field.fBadDefault = badDefault
|
||||||
self.fFields.append(field)
|
self.fFields.append(field)
|
||||||
return field
|
return field
|
||||||
|
|
||||||
@ -107,17 +152,26 @@ class PdfClass:
|
|||||||
self.fIncludes.append(path)
|
self.fIncludes.append(path)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def carbonCopy(self, cc):
|
def carbonCopyPublic(self, cc):
|
||||||
self.fCC.append(cc)
|
self.fCCPublic.append(cc)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def carbonCopyPrivate(self, cc):
|
||||||
|
self.fCCPrivate.append(cc)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
class PdfClassManager:
|
class PdfClassManager:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.fClasses = {}
|
self.fClasses = {}
|
||||||
|
self.fClassesNamesInOrder = []
|
||||||
|
|
||||||
def addClass(self, name, base=''):
|
def addClass(self, name, base='Object'):
|
||||||
cls = PdfClass(name, base)
|
if name == 'Object':
|
||||||
|
cls = PdfClass(name, '')
|
||||||
|
else:
|
||||||
|
cls = PdfClass(name, base)
|
||||||
self.fClasses[name] = cls
|
self.fClasses[name] = cls
|
||||||
|
self.fClassesNamesInOrder.append(name)
|
||||||
return cls
|
return cls
|
||||||
|
|
||||||
def longName(self, name):
|
def longName(self, name):
|
||||||
@ -143,6 +197,45 @@ class PdfClassManager:
|
|||||||
if cnt != 0:
|
if cnt != 0:
|
||||||
print(' ' + cls.fEnumEnd + ',')
|
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):
|
def write(self):
|
||||||
# generate enum
|
# generate enum
|
||||||
enumsRoot = []
|
enumsRoot = []
|
||||||
@ -152,8 +245,8 @@ class PdfClassManager:
|
|||||||
for name in self.fClasses:
|
for name in self.fClasses:
|
||||||
cls = self.fClasses[name]
|
cls = self.fClasses[name]
|
||||||
enum = self.longName(name)
|
enum = self.longName(name)
|
||||||
cls.fEnum = 'k' + enum + '_PdfObjectType'
|
cls.fEnum = 'k' + enum + '_SkPdfObjectType'
|
||||||
cls.fEnumEnd = 'k' + enum + '__End_PdfObjectType'
|
cls.fEnumEnd = 'k' + enum + '__End_SkPdfObjectType'
|
||||||
|
|
||||||
if cls.fBase != '':
|
if cls.fBase != '':
|
||||||
self.fClasses[cls.fBase].fEnumSubclasses.append(cls.fEnum)
|
self.fClasses[cls.fBase].fEnumSubclasses.append(cls.fEnum)
|
||||||
@ -165,14 +258,138 @@ class PdfClassManager:
|
|||||||
|
|
||||||
enumsRoot.sort()
|
enumsRoot.sort()
|
||||||
|
|
||||||
|
|
||||||
|
# TODO(edisonn): move each .h in it's own file
|
||||||
|
# write imports
|
||||||
|
|
||||||
# write enums
|
# write enums
|
||||||
print('enum PdfObjectType {')
|
print('enum SkPdfObjectType {')
|
||||||
for enum in enumsRoot:
|
for enum in enumsRoot:
|
||||||
self.writeEnum(enum, enumToCls)
|
self.writeEnum(enum, enumToCls)
|
||||||
print('};')
|
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
|
# 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
|
return
|
||||||
|
|
||||||
def generateCode():
|
def generateCode():
|
||||||
@ -189,22 +406,28 @@ def generateCode():
|
|||||||
all.addClass('Array')
|
all.addClass('Array')
|
||||||
all.addClass('Dictionary')
|
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()\
|
all.addClass('Image', 'XObject').required('""').field('Type').must(PdfName('XObject')).name('t').done()\
|
||||||
.required().hasField('/Subtype').must('/Image').done()\
|
.done()\
|
||||||
.required().hasField('/Width', '/W').integer().done().done()\
|
.required('""').field('Subtype').must(PdfName('Image')).name('s').done()\
|
||||||
.required().hasField('/Height', '/H').integer().done().done()\
|
.done()\
|
||||||
.required().hasField('/ColorSpace').multiple([PdfName('/DeviceRGB', '/RGB'), PdfName('/DeviceGray', '/Gray')])\
|
.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()\
|
||||||
.done()\
|
.carbonCopyPrivate('SkBitmap bitmap;')
|
||||||
.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()\
|
all.addClass('Form', 'XObject').required('""').field('Type').must(PdfName('XObject')).name('t').done()\
|
||||||
.required().hasField('/Subtype').must('/Form').done()
|
.done()\
|
||||||
|
.required('""').field('Subtype').must(PdfName('Form')).name('s').done()\
|
||||||
|
.done()\
|
||||||
|
.carbonCopyPublic('void test() {}')
|
||||||
|
|
||||||
|
|
||||||
all.write()
|
all.write()
|
||||||
|
@ -22,6 +22,29 @@
|
|||||||
#include <stack>
|
#include <stack>
|
||||||
|
|
||||||
#include "podofo.h"
|
#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
|
* TODO(edisonn): ASAP so skp -> pdf -> png looks greap
|
||||||
@ -31,7 +54,7 @@
|
|||||||
* - load font for youtube.pdf
|
* - load font for youtube.pdf
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//#define PDF_TRACE
|
#define PDF_TRACE
|
||||||
//#define PDF_TRACE_DIFF_IN_PNG
|
//#define PDF_TRACE_DIFF_IN_PNG
|
||||||
//#define PDF_DEBUG_NO_CLIPING
|
//#define PDF_DEBUG_NO_CLIPING
|
||||||
//#define PDF_DEBUG_NO_PAGE_CLIPING
|
//#define PDF_DEBUG_NO_PAGE_CLIPING
|
||||||
@ -78,9 +101,9 @@ int GetColorSpaceComponents(const std::string& colorSpace) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PdfObject* resolveReferenceObject(PdfMemDocument* pdfDoc,
|
const PdfObject* resolveReferenceObject(const PdfMemDocument* pdfDoc,
|
||||||
PdfObject* obj,
|
const PdfObject* obj,
|
||||||
bool resolveOneElementArrays = false) {
|
bool resolveOneElementArrays = false) {
|
||||||
while (obj && (obj->IsReference() || (resolveOneElementArrays &&
|
while (obj && (obj->IsReference() || (resolveOneElementArrays &&
|
||||||
obj->IsArray() &&
|
obj->IsArray() &&
|
||||||
obj->GetArray().GetSize() == 1))) {
|
obj->GetArray().GetSize() == 1))) {
|
||||||
@ -152,7 +175,7 @@ struct PdfGraphicsState {
|
|||||||
double fWordSpace;
|
double fWordSpace;
|
||||||
double fCharSpace;
|
double fCharSpace;
|
||||||
|
|
||||||
PdfObject* fObjectWithResources;
|
const PdfObject* fObjectWithResources;
|
||||||
|
|
||||||
SkBitmap fSMask;
|
SkBitmap fSMask;
|
||||||
|
|
||||||
@ -562,7 +585,7 @@ PdfEncoding* FixPdfFont(PdfContext* pdfContext, PdfFont* fCurFont) {
|
|||||||
if (fCurFont->GetObject()->IsDictionary() && fCurFont->GetObject()->GetDictionary().HasKey(PdfName("ToUnicode"))) {
|
if (fCurFont->GetObject()->IsDictionary() && fCurFont->GetObject()->GetDictionary().HasKey(PdfName("ToUnicode"))) {
|
||||||
PdfCMapEncoding* enc = new PdfCMapEncoding(
|
PdfCMapEncoding* enc = new PdfCMapEncoding(
|
||||||
fCurFont->GetObject(),
|
fCurFont->GetObject(),
|
||||||
resolveReferenceObject(pdfContext->fPdfDoc,
|
(PdfObject*)resolveReferenceObject(pdfContext->fPdfDoc,
|
||||||
fCurFont->GetObject()->GetDictionary().GetKey(PdfName("ToUnicode"))),
|
fCurFont->GetObject()->GetDictionary().GetKey(PdfName("ToUnicode"))),
|
||||||
PdfCMapEncoding::eBaseEncoding_Identity); // todo, read the base encoding
|
PdfCMapEncoding::eBaseEncoding_Identity); // todo, read the base encoding
|
||||||
gFontsFixed[fCurFont] = enc;
|
gFontsFixed[fCurFont] = enc;
|
||||||
@ -728,12 +751,12 @@ PdfResult PdfOp_Tc(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo
|
|||||||
|
|
||||||
// TODO(edisonn): deal with synonyms (/BPC == /BitsPerComponent), here or in GetKey?
|
// 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
|
// Always pass long form in key, and have a map of long -> short key
|
||||||
bool LongFromDictionary(PdfContext* pdfContext,
|
bool LongFromDictionary(const PdfMemDocument* pdfDoc,
|
||||||
PdfDictionary& dict,
|
const PdfDictionary& dict,
|
||||||
const char* key,
|
const char* key,
|
||||||
long* data) {
|
long* data) {
|
||||||
PdfObject* value = resolveReferenceObject(pdfContext->fPdfDoc,
|
const PdfObject* value = resolveReferenceObject(pdfDoc,
|
||||||
dict.GetKey(PdfName(key)));
|
dict.GetKey(PdfName(key)));
|
||||||
|
|
||||||
if (value == NULL || !value->IsNumber()) {
|
if (value == NULL || !value->IsNumber()) {
|
||||||
return false;
|
return false;
|
||||||
@ -743,12 +766,22 @@ bool LongFromDictionary(PdfContext* pdfContext,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BoolFromDictionary(PdfContext* pdfContext,
|
bool LongFromDictionary(const PdfMemDocument* pdfDoc,
|
||||||
PdfDictionary& dict,
|
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,
|
const char* key,
|
||||||
bool* data) {
|
bool* data) {
|
||||||
PdfObject* value = resolveReferenceObject(pdfContext->fPdfDoc,
|
const PdfObject* value = resolveReferenceObject(pdfDoc,
|
||||||
dict.GetKey(PdfName(key)));
|
dict.GetKey(PdfName(key)));
|
||||||
|
|
||||||
if (value == NULL || !value->IsBool()) {
|
if (value == NULL || !value->IsBool()) {
|
||||||
return false;
|
return false;
|
||||||
@ -758,13 +791,23 @@ bool BoolFromDictionary(PdfContext* pdfContext,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NameFromDictionary(PdfContext* pdfContext,
|
bool BoolFromDictionary(const PdfMemDocument* pdfDoc,
|
||||||
PdfDictionary& dict,
|
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,
|
const char* key,
|
||||||
std::string* data) {
|
std::string* data) {
|
||||||
PdfObject* value = resolveReferenceObject(pdfContext->fPdfDoc,
|
const PdfObject* value = resolveReferenceObject(pdfDoc,
|
||||||
dict.GetKey(PdfName(key)),
|
dict.GetKey(PdfName(key)),
|
||||||
true);
|
true);
|
||||||
if (value == NULL || !value->IsName()) {
|
if (value == NULL || !value->IsName()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -773,6 +816,16 @@ bool NameFromDictionary(PdfContext* pdfContext,
|
|||||||
return true;
|
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!!!
|
// TODO(edisonn): perf!!!
|
||||||
|
|
||||||
static SkColorTable* getGrayColortable() {
|
static SkColorTable* getGrayColortable() {
|
||||||
@ -899,14 +952,81 @@ bool transferImageStreamToARGB(unsigned char* uncompressedStream, pdf_long uncom
|
|||||||
|
|
||||||
// this functions returns the image, it does not look at the smask.
|
// 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 ||
|
if (!obj.HasStream() || obj.GetStream() == NULL || obj.GetStream()->GetLength() == 0 ||
|
||||||
!obj.IsDictionary()) {
|
!obj.IsDictionary()) {
|
||||||
// TODO(edisonn): report warning to be used in testing.
|
// TODO(edisonn): report warning to be used in testing.
|
||||||
return SkBitmap();
|
return SkBitmap();
|
||||||
}
|
}
|
||||||
|
|
||||||
PdfObject* value = resolveReferenceObject(pdfContext->fPdfDoc,
|
const PdfObject* value = resolveReferenceObject(pdfContext->fPdfDoc,
|
||||||
obj.GetDictionary().GetKey(PdfName("Filter")));
|
obj.GetDictionary().GetKey(PdfName("Filter")));
|
||||||
|
|
||||||
if (value && value->IsArray() && value->GetArray().GetSize() == 1) {
|
if (value && value->IsArray() && value->GetArray().GetSize() == 1) {
|
||||||
@ -924,10 +1044,10 @@ SkBitmap getImageFromObject(PdfContext* pdfContext, PdfObject& obj, bool transpa
|
|||||||
// translate
|
// translate
|
||||||
|
|
||||||
long bpc = 0;
|
long bpc = 0;
|
||||||
LongFromDictionary(pdfContext, obj.GetDictionary(), "BitsPerComponent", &bpc);
|
LongFromDictionary(pdfContext->fPdfDoc, obj.GetDictionary(), "BitsPerComponent", "BPC", &bpc);
|
||||||
|
|
||||||
bool imageMask = false;
|
bool imageMask = false;
|
||||||
BoolFromDictionary(pdfContext, obj.GetDictionary(), "ImageMask", &imageMask);
|
BoolFromDictionary(pdfContext->fPdfDoc, obj.GetDictionary(), "ImageMask", "", &imageMask);
|
||||||
|
|
||||||
if (imageMask) {
|
if (imageMask) {
|
||||||
if (bpc != 0 && bpc != 1) {
|
if (bpc != 0 && bpc != 1) {
|
||||||
@ -938,19 +1058,19 @@ SkBitmap getImageFromObject(PdfContext* pdfContext, PdfObject& obj, bool transpa
|
|||||||
}
|
}
|
||||||
|
|
||||||
long width;
|
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.
|
// TODO(edisonn): report warning to be used in testing.
|
||||||
return SkBitmap();
|
return SkBitmap();
|
||||||
}
|
}
|
||||||
|
|
||||||
long height;
|
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.
|
// TODO(edisonn): report warning to be used in testing.
|
||||||
return SkBitmap();
|
return SkBitmap();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string colorSpace; // TODO(edisonn): load others than names, for more complicated
|
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.
|
// TODO(edisonn): report warning to be used in testing.
|
||||||
return SkBitmap();
|
return SkBitmap();
|
||||||
}
|
}
|
||||||
@ -985,8 +1105,29 @@ SkBitmap getImageFromObject(PdfContext* pdfContext, PdfObject& obj, bool transpa
|
|||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
SkBitmap getSmaskFromObject(PdfContext* pdfContext, PdfObject& obj) {
|
SkBitmap getSmaskFromObject(PdfContext* pdfContext, const SkPdfImage* obj) {
|
||||||
PdfObject* sMask = resolveReferenceObject(pdfContext->fPdfDoc,
|
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")));
|
obj.GetDictionary().GetKey(PdfName("SMask")));
|
||||||
|
|
||||||
#ifdef PDF_TRACE
|
#ifdef PDF_TRACE
|
||||||
@ -998,21 +1139,21 @@ SkBitmap getSmaskFromObject(PdfContext* pdfContext, PdfObject& obj) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (sMask) {
|
if (sMask) {
|
||||||
return getImageFromObject(pdfContext, *sMask, true);
|
return getImageFromObjectOld(pdfContext, *sMask, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(edisonn): implement GS SMask. Default to empty right now.
|
// TODO(edisonn): implement GS SMask. Default to empty right now.
|
||||||
return pdfContext->fGraphicsState.fSMask;
|
return pdfContext->fGraphicsState.fSMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
PdfResult doXObject_Image(PdfContext* pdfContext, SkCanvas* canvas, PdfObject& obj) {
|
|
||||||
if (!obj.HasStream() || obj.GetStream() == NULL || obj.GetStream()->GetLength() == 0 ||
|
PdfResult doXObject_Image(PdfContext* pdfContext, SkCanvas* canvas, const SkPdfImage* skpdfimage) {
|
||||||
!obj.IsDictionary()) {
|
if (skpdfimage == NULL || !skpdfimage->valid()) {
|
||||||
return kIgnoreError_PdfResult;
|
return kIgnoreError_PdfResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
SkBitmap image = getImageFromObject(pdfContext, obj, false);
|
SkBitmap image = getImageFromObject(pdfContext, skpdfimage, false);
|
||||||
SkBitmap sMask = getSmaskFromObject(pdfContext, obj);
|
SkBitmap sMask = getSmaskFromObject(pdfContext, skpdfimage);
|
||||||
|
|
||||||
canvas->save();
|
canvas->save();
|
||||||
canvas->setMatrix(pdfContext->fGraphicsState.fMatrix);
|
canvas->setMatrix(pdfContext->fGraphicsState.fMatrix);
|
||||||
@ -1034,13 +1175,43 @@ PdfResult doXObject_Image(PdfContext* pdfContext, SkCanvas* canvas, PdfObject& o
|
|||||||
return kPartial_PdfResult;
|
return kPartial_PdfResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
PdfResult doXObject_ImageOld(PdfContext* pdfContext, SkCanvas* canvas, PdfObject& obj) {
|
PdfResult doXObject_ImageOld(PdfContext* pdfContext, SkCanvas* canvas, const PdfObject& obj) {
|
||||||
if (!obj.HasStream() || obj.GetStream() == NULL || obj.GetStream()->GetLength() == 0 ||
|
if (!obj.HasStream() || obj.GetStream() == NULL || obj.GetStream()->GetLength() == 0 ||
|
||||||
!obj.IsDictionary()) {
|
!obj.IsDictionary()) {
|
||||||
return kIgnoreError_PdfResult;
|
return kIgnoreError_PdfResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
PdfObject* sMask = resolveReferenceObject(pdfContext->fPdfDoc,
|
SkBitmap image = getImageFromObjectOld(pdfContext, obj, false);
|
||||||
|
SkBitmap sMask = getSmaskFromObjectOld(pdfContext, obj);
|
||||||
|
|
||||||
|
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_ImageOld2(PdfContext* pdfContext, SkCanvas* canvas, const PdfObject& obj) {
|
||||||
|
if (!obj.HasStream() || obj.GetStream() == NULL || obj.GetStream()->GetLength() == 0 ||
|
||||||
|
!obj.IsDictionary()) {
|
||||||
|
return kIgnoreError_PdfResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
const PdfObject* sMask = resolveReferenceObject(pdfContext->fPdfDoc,
|
||||||
obj.GetDictionary().GetKey(PdfName("SMask")));
|
obj.GetDictionary().GetKey(PdfName("SMask")));
|
||||||
// TODO(edisonn): else get smask from graphi state
|
// TODO(edisonn): else get smask from graphi state
|
||||||
// TODO(edisonn): add utility, SkBitmap loadBitmap(PdfObject& obj, bool no_smask);
|
// TODO(edisonn): add utility, SkBitmap loadBitmap(PdfObject& obj, bool no_smask);
|
||||||
@ -1054,6 +1225,8 @@ PdfResult doXObject_ImageOld(PdfContext* pdfContext, SkCanvas* canvas, PdfObject
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
// TODO (edisonn): Fast Jpeg(DCTDecode) draw, or fast PNG(FlateDecode) draw ...
|
||||||
PdfObject* value = resolveReferenceObject(pdfContext->fPdfDoc,
|
PdfObject* value = resolveReferenceObject(pdfContext->fPdfDoc,
|
||||||
obj.GetDictionary().GetKey(PdfName("Filter")));
|
obj.GetDictionary().GetKey(PdfName("Filter")));
|
||||||
|
|
||||||
@ -1062,20 +1235,19 @@ PdfResult doXObject_ImageOld(PdfContext* pdfContext, SkCanvas* canvas, PdfObject
|
|||||||
&value->GetArray()[0]);
|
&value->GetArray()[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO (edisonn): Fast Jpeg(DCTDecode) draw, or fast PNG(FlateDecode) draw ...
|
if (value && value->IsName() && value->GetName().GetName() == "DCTDecode") {
|
||||||
// if (value && value->IsName() && value->GetName().GetName() == "DCTDecode") {
|
SkStream stream = SkStream::
|
||||||
// SkStream stream = SkStream::
|
SkImageDecoder::Factory()
|
||||||
// SkImageDecoder::Factory()
|
}
|
||||||
// }
|
*/
|
||||||
|
|
||||||
// Get color space
|
// Get color space
|
||||||
// trasnlate
|
// trasnlate
|
||||||
|
|
||||||
long bpc = 0;
|
long bpc = 0;
|
||||||
LongFromDictionary(pdfContext, obj.GetDictionary(), "BitsPerComponent", &bpc);
|
LongFromDictionary(pdfContext->fPdfDoc, obj.GetDictionary(), "BitsPerComponent", "BPC", &bpc);
|
||||||
|
|
||||||
bool imageMask = false;
|
bool imageMask = false;
|
||||||
BoolFromDictionary(pdfContext, obj.GetDictionary(), "ImageMask", &imageMask);
|
BoolFromDictionary(pdfContext->fPdfDoc, obj.GetDictionary(), "ImageMask", "", &imageMask);
|
||||||
|
|
||||||
if (imageMask) {
|
if (imageMask) {
|
||||||
if (bpc != 0 && bpc != 1) {
|
if (bpc != 0 && bpc != 1) {
|
||||||
@ -1085,17 +1257,17 @@ PdfResult doXObject_ImageOld(PdfContext* pdfContext, SkCanvas* canvas, PdfObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
long width;
|
long width;
|
||||||
if (!LongFromDictionary(pdfContext, obj.GetDictionary(), "Width", &width)) {
|
if (!LongFromDictionary(pdfContext->fPdfDoc, obj.GetDictionary(), "Width", "W", &width)) {
|
||||||
return kIgnoreError_PdfResult;
|
return kIgnoreError_PdfResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
long height;
|
long height;
|
||||||
if (!LongFromDictionary(pdfContext, obj.GetDictionary(), "Height", &height)) {
|
if (!LongFromDictionary(pdfContext->fPdfDoc, obj.GetDictionary(), "Height", "H", &height)) {
|
||||||
return kIgnoreError_PdfResult;
|
return kIgnoreError_PdfResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string colorSpace; // TODO(edisonn): load others than names, for more complicated
|
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;
|
return kIgnoreError_PdfResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1146,10 +1318,10 @@ PdfResult doXObject_ImageOld(PdfContext* pdfContext, SkCanvas* canvas, PdfObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool SkMatrixFromDictionary(PdfContext* pdfContext,
|
bool SkMatrixFromDictionary(PdfContext* pdfContext,
|
||||||
PdfDictionary& dict,
|
const PdfDictionary& dict,
|
||||||
const char* key,
|
const char* key,
|
||||||
SkMatrix* matrix) {
|
SkMatrix* matrix) {
|
||||||
PdfObject* value = resolveReferenceObject(pdfContext->fPdfDoc,
|
const PdfObject* value = resolveReferenceObject(pdfContext->fPdfDoc,
|
||||||
dict.GetKey(PdfName(key)));
|
dict.GetKey(PdfName(key)));
|
||||||
|
|
||||||
if (value == NULL || !value->IsArray()) {
|
if (value == NULL || !value->IsArray()) {
|
||||||
@ -1162,7 +1334,7 @@ bool SkMatrixFromDictionary(PdfContext* pdfContext,
|
|||||||
|
|
||||||
double array[6];
|
double array[6];
|
||||||
for (int i = 0; i < 6; i++) {
|
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())) {
|
if (elem == NULL || (!elem->IsReal() && !elem->IsNumber())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1174,10 +1346,10 @@ bool SkMatrixFromDictionary(PdfContext* pdfContext,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool SkRectFromDictionary(PdfContext* pdfContext,
|
bool SkRectFromDictionary(PdfContext* pdfContext,
|
||||||
PdfDictionary& dict,
|
const PdfDictionary& dict,
|
||||||
const char* key,
|
const char* key,
|
||||||
SkRect* rect) {
|
SkRect* rect) {
|
||||||
PdfObject* value = resolveReferenceObject(pdfContext->fPdfDoc,
|
const PdfObject* value = resolveReferenceObject(pdfContext->fPdfDoc,
|
||||||
dict.GetKey(PdfName(key)));
|
dict.GetKey(PdfName(key)));
|
||||||
|
|
||||||
if (value == NULL || !value->IsArray()) {
|
if (value == NULL || !value->IsArray()) {
|
||||||
@ -1190,7 +1362,7 @@ bool SkRectFromDictionary(PdfContext* pdfContext,
|
|||||||
|
|
||||||
double array[4];
|
double array[4];
|
||||||
for (int i = 0; i < 4; i++) {
|
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())) {
|
if (elem == NULL || (!elem->IsReal() && !elem->IsNumber())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1204,7 +1376,7 @@ bool SkRectFromDictionary(PdfContext* pdfContext,
|
|||||||
return true;
|
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) {
|
if (!obj.HasStream() || obj.GetStream() == NULL || obj.GetStream()->GetLength() == 0) {
|
||||||
return kOK_PdfResult;
|
return kOK_PdfResult;
|
||||||
}
|
}
|
||||||
@ -1261,17 +1433,17 @@ PdfResult doXObject_Form(PdfContext* pdfContext, SkCanvas* canvas, PdfObject& ob
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
PdfResult doXObject_PS(PdfContext* pdfContext, SkCanvas* canvas, PdfObject& obj) {
|
PdfResult doXObject_PS(PdfContext* pdfContext, SkCanvas* canvas, const PdfObject& obj) {
|
||||||
return kNYI_PdfResult;
|
return kNYI_PdfResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(edisonn): faster, have the property on the PdfObject itself.
|
// TODO(edisonn): faster, have the property on the PdfObject itself.
|
||||||
std::set<PdfObject*> gInRendering;
|
std::set<const PdfObject*> gInRendering;
|
||||||
|
|
||||||
class CheckRecursiveRendering {
|
class CheckRecursiveRendering {
|
||||||
PdfObject& fObj;
|
const PdfObject& fObj;
|
||||||
public:
|
public:
|
||||||
CheckRecursiveRendering(PdfObject& obj) : fObj(obj) {
|
CheckRecursiveRendering(const PdfObject& obj) : fObj(obj) {
|
||||||
gInRendering.insert(&obj);
|
gInRendering.insert(&obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1280,12 +1452,41 @@ public:
|
|||||||
gInRendering.erase(&fObj);
|
gInRendering.erase(&fObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsInRendering(PdfObject& obj) {
|
static bool IsInRendering(const PdfObject& obj) {
|
||||||
return gInRendering.find(&obj) != gInRendering.end();
|
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)) {
|
if (CheckRecursiveRendering::IsInRendering(obj)) {
|
||||||
// Oops, corrupt PDF!
|
// Oops, corrupt PDF!
|
||||||
return kIgnoreError_PdfResult;
|
return kIgnoreError_PdfResult;
|
||||||
@ -1297,7 +1498,7 @@ PdfResult doXObject(PdfContext* pdfContext, SkCanvas* canvas, PdfObject& obj) {
|
|||||||
return kIgnoreError_PdfResult;
|
return kIgnoreError_PdfResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
PdfObject* type = resolveReferenceObject(pdfContext->fPdfDoc,
|
const PdfObject* type = resolveReferenceObject(pdfContext->fPdfDoc,
|
||||||
obj.GetDictionary().GetKey(PdfName("Type")));
|
obj.GetDictionary().GetKey(PdfName("Type")));
|
||||||
|
|
||||||
if (type == NULL || !type->IsName()) {
|
if (type == NULL || !type->IsName()) {
|
||||||
@ -1308,7 +1509,7 @@ PdfResult doXObject(PdfContext* pdfContext, SkCanvas* canvas, PdfObject& obj) {
|
|||||||
return kIgnoreError_PdfResult;
|
return kIgnoreError_PdfResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
PdfObject* subtype =
|
const PdfObject* subtype =
|
||||||
resolveReferenceObject(pdfContext->fPdfDoc,
|
resolveReferenceObject(pdfContext->fPdfDoc,
|
||||||
obj.GetDictionary().GetKey(PdfName("Subtype")));
|
obj.GetDictionary().GetKey(PdfName("Subtype")));
|
||||||
|
|
||||||
@ -1317,7 +1518,7 @@ PdfResult doXObject(PdfContext* pdfContext, SkCanvas* canvas, PdfObject& obj) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (subtype->GetName().GetName() == "Image") {
|
if (subtype->GetName().GetName() == "Image") {
|
||||||
return doXObject_Image(pdfContext, canvas, obj);
|
return doXObject_ImageOld(pdfContext, canvas, obj);
|
||||||
} else if (subtype->GetName().GetName() == "Form") {
|
} else if (subtype->GetName().GetName() == "Form") {
|
||||||
return doXObject_Form(pdfContext, canvas, obj);
|
return doXObject_Form(pdfContext, canvas, obj);
|
||||||
} else if (subtype->GetName().GetName() == "PS") {
|
} else if (subtype->GetName().GetName() == "PS") {
|
||||||
@ -2058,8 +2259,8 @@ PdfResult PdfOp_i(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** loo
|
|||||||
PdfResult PdfOp_gs(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
|
PdfResult PdfOp_gs(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
|
||||||
PdfName name = pdfContext->fVarStack.top().GetName(); pdfContext->fVarStack.pop();
|
PdfName name = pdfContext->fVarStack.top().GetName(); pdfContext->fVarStack.pop();
|
||||||
|
|
||||||
PdfDictionary& pageDict = pdfContext->fGraphicsState.fObjectWithResources->GetDictionary();
|
const PdfDictionary& pageDict = pdfContext->fGraphicsState.fObjectWithResources->GetDictionary();
|
||||||
PdfObject* resources = resolveReferenceObject(pdfContext->fPdfDoc,
|
const PdfObject* resources = resolveReferenceObject(pdfContext->fPdfDoc,
|
||||||
pageDict.GetKey("Resources"));
|
pageDict.GetKey("Resources"));
|
||||||
|
|
||||||
if (resources == NULL) {
|
if (resources == NULL) {
|
||||||
@ -2082,9 +2283,9 @@ PdfResult PdfOp_gs(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo
|
|||||||
return kIgnoreError_PdfResult;
|
return kIgnoreError_PdfResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
PdfDictionary& resourceDict = resources->GetDictionary();
|
const PdfDictionary& resourceDict = resources->GetDictionary();
|
||||||
//Next, get the ExtGState Dictionary from the Resource Dictionary:
|
//Next, get the ExtGState Dictionary from the Resource Dictionary:
|
||||||
PdfObject* extGStateDictionary = resolveReferenceObject(pdfContext->fPdfDoc,
|
const PdfObject* extGStateDictionary = resolveReferenceObject(pdfContext->fPdfDoc,
|
||||||
resourceDict.GetKey("ExtGState"));
|
resourceDict.GetKey("ExtGState"));
|
||||||
|
|
||||||
if (extGStateDictionary == NULL) {
|
if (extGStateDictionary == NULL) {
|
||||||
@ -2101,7 +2302,7 @@ PdfResult PdfOp_gs(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo
|
|||||||
return kIgnoreError_PdfResult;
|
return kIgnoreError_PdfResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
PdfObject* value =
|
const PdfObject* value =
|
||||||
resolveReferenceObject(pdfContext->fPdfDoc,
|
resolveReferenceObject(pdfContext->fPdfDoc,
|
||||||
extGStateDictionary->GetDictionary().GetKey(name));
|
extGStateDictionary->GetDictionary().GetKey(name));
|
||||||
|
|
||||||
@ -2200,8 +2401,8 @@ PdfResult PdfOp_sh(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo
|
|||||||
PdfResult PdfOp_Do(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
|
PdfResult PdfOp_Do(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
|
||||||
PdfName name = pdfContext->fVarStack.top().GetName(); pdfContext->fVarStack.pop();
|
PdfName name = pdfContext->fVarStack.top().GetName(); pdfContext->fVarStack.pop();
|
||||||
|
|
||||||
PdfDictionary& pageDict = pdfContext->fGraphicsState.fObjectWithResources->GetDictionary();
|
const PdfDictionary& pageDict = pdfContext->fGraphicsState.fObjectWithResources->GetDictionary();
|
||||||
PdfObject* resources = resolveReferenceObject(pdfContext->fPdfDoc,
|
const PdfObject* resources = resolveReferenceObject(pdfContext->fPdfDoc,
|
||||||
pageDict.GetKey("Resources"));
|
pageDict.GetKey("Resources"));
|
||||||
|
|
||||||
if (resources == NULL) {
|
if (resources == NULL) {
|
||||||
@ -2224,9 +2425,9 @@ PdfResult PdfOp_Do(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo
|
|||||||
return kIgnoreError_PdfResult;
|
return kIgnoreError_PdfResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
PdfDictionary& resourceDict = resources->GetDictionary();
|
const PdfDictionary& resourceDict = resources->GetDictionary();
|
||||||
//Next, get the XObject Dictionary from the Resource Dictionary:
|
//Next, get the XObject Dictionary from the Resource Dictionary:
|
||||||
PdfObject* xObjectDictionary = resolveReferenceObject(pdfContext->fPdfDoc,
|
const PdfObject* xObjectDictionary = resolveReferenceObject(pdfContext->fPdfDoc,
|
||||||
resourceDict.GetKey("XObject"));
|
resourceDict.GetKey("XObject"));
|
||||||
|
|
||||||
if (xObjectDictionary == NULL) {
|
if (xObjectDictionary == NULL) {
|
||||||
@ -2243,7 +2444,7 @@ PdfResult PdfOp_Do(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo
|
|||||||
return kIgnoreError_PdfResult;
|
return kIgnoreError_PdfResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
PdfObject* value =
|
const PdfObject* value =
|
||||||
resolveReferenceObject(pdfContext->fPdfDoc,
|
resolveReferenceObject(pdfContext->fPdfDoc,
|
||||||
xObjectDictionary->GetDictionary().GetKey(name));
|
xObjectDictionary->GetDictionary().GetKey(name));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user