2013-06-12 19:07:45 +00:00
2013-06-11 21:44:08 +00:00
2013-06-14 19:22:19 +00:00
import sys
2013-06-12 19:07:45 +00:00
2013-06-14 19:22:19 +00:00
import datatypes
2013-06-25 20:45:40 +00:00
from autogen . pdfspec_autogen import *
2013-06-11 21:44:08 +00:00
2013-07-10 17:09:50 +00:00
# TODO(edisonn): date and some other types are in fact strings, with a custom format!!!
# TODO(edisonn): refer to page 99 (PDF data types)
2013-06-17 23:36:45 +00:00
knowTypes = {
2013-07-10 17:09:50 +00:00
' (any) ' : [ ' SkPdfObject* ' , ' ret ' , datatypes . CppNull ( ) , ' true ' , ' use a mapper ' ] ,
# TODO(edisonn): return constant for undefined
' (undefined) ' : [ ' SkPdfObject* ' , ' ret ' , datatypes . CppNull ( ) , ' true ' , ' use a mapper ' ] ,
' (various) ' : [ ' SkPdfObject* ' , ' ret ' , datatypes . CppNull ( ) , ' true ' , ' use a mapper ' ] ,
' array ' : [ ' SkPdfArray* ' , ' (SkPdfArray*)ret ' , datatypes . CppNull ( ) , ' ret->isArray() ' ] ,
' boolean ' : [ ' bool ' , ' ret->boolValue() ' , datatypes . PdfBoolean ( ' false ' ) , ' ret->isBoolean() ' ] ,
#date is a string, with special formating, add here the
' date ' : [ ' SkPdfDate ' , ' ret->dateValue() ' , datatypes . PdfDateNever ( ) , ' ret->isDate() ' ] ,
' dictionary ' : [ ' SkPdfDictionary* ' , ' (SkPdfDictionary*)ret ' , datatypes . CppNull ( ) , ' ret->isDictionary() ' , ' use a mapper ' ] ,
' function ' : [ ' SkPdfFunction ' , ' ret->functionValue() ' , datatypes . PdfFunctionNone ( ) , ' ret->isFunction() ' ] ,
' integer ' : [ ' int64_t ' , ' ret->intValue() ' , datatypes . PdfInteger ( 0 ) , ' ret->isInteger() ' ] ,
' file_specification ' : [ ' SkPdfFileSpec ' , ' ret->fileSpecValue() ' , datatypes . FileSpecNone ( ) , ' false ' ] ,
' name ' : [ ' std::string ' , ' ret->nameValue2() ' , datatypes . PdfString ( ' " " ' ) , ' ret->isName() ' ] ,
#should assert, references should never be allowed here, should be resolved way earlier
' tree ' : [ ' SkPdfTree ' , ' ret->treeValue() ' , datatypes . EmptyTree ( ) , ' false ' ] ,
' number ' : [ ' double ' , ' ret->numberValue() ' , datatypes . PdfNumber ( 0 ) , ' ret->isNumber() ' ] ,
' rectangle ' : [ ' SkRect ' , ' ret->rectangleValue() ' , datatypes . EmptyRect ( ) , ' ret->isRectangle() ' ] ,
' stream ' : [ ' SkPdfStream* ' , ' ret->getStream() ' , datatypes . CppNull ( ) , ' ret->hasStream() ' ] ,
' string ' : [ ' std::string ' , ' ret->stringValue2() ' , datatypes . PdfString ( ' " " ' ) , ' ret->isAnyString() ' ] ,
' text ' : [ ' std::string ' , ' ret->stringValue2() ' , datatypes . PdfString ( ' " " ' ) , ' ret->isAnyString() ' ] ,
' text string ' : [ ' std::string ' , ' ret->stringValue2() ' , datatypes . PdfString ( ' " " ' ) , ' ret->isAnyString() ' ] ,
' matrix ' : [ ' SkMatrix ' , ' ret->matrixValue() ' , datatypes . IdentityMatrix ( ) , ' ret->isMatrix() ' ] ,
2013-06-17 23:36:45 +00:00
}
2013-06-13 20:02:29 +00:00
2013-06-11 21:44:08 +00:00
class PdfField :
def __init__ ( self , parent , name , abr ) :
self . fParent = parent
self . fName = name
self . fAbr = abr
self . fDefault = ' '
2013-06-17 23:36:45 +00:00
self . fTypes = ' '
2013-06-12 19:07:45 +00:00
self . fCppName = ' '
2013-06-17 23:36:45 +00:00
self . fEnumValues = [ ]
self . fHasMust = False
2013-06-21 21:03:15 +00:00
self . fMustBe = [ ]
2013-06-19 17:42:17 +00:00
self . fComment = ' '
2013-06-11 21:44:08 +00:00
def must ( self , value ) :
2013-06-12 19:07:45 +00:00
self . fHasMust = True
self . fMustBe = value
return self
2013-06-11 21:44:08 +00:00
def default ( self , value ) :
self . fDefault = value
return self
2013-06-17 23:36:45 +00:00
def multiple ( self , enumValues ) :
self . fEnumValues = enumValues
2013-06-11 21:44:08 +00:00
return self
2013-06-12 19:07:45 +00:00
def name ( self , name ) :
self . fCppName = name
2013-06-11 21:44:08 +00:00
return self
2013-06-17 23:36:45 +00:00
def type ( self , types ) :
2013-06-13 20:02:29 +00:00
# TODO (edisonn): if simple type, use it, otherwise set it to Dictionary, and set a mask for valid types, like array or name
2013-06-17 23:36:45 +00:00
types = types . strip ( )
2013-06-27 20:03:43 +00:00
types = types . replace ( ' or ' , ' ' )
types = types . replace ( ' or, ' , ' ' )
types = types . replace ( ' ,or ' , ' ' )
types = types . replace ( ' ,or, ' , ' ' )
2013-06-17 23:36:45 +00:00
types = types . replace ( ' , ' , ' ' )
types = types . replace ( ' text ' , ' ' ) # TODO(edisonn): what is the difference between 'text string' and 'string'?
types = types . replace ( ' file specification ' , ' file_specification ' )
2013-06-14 19:22:19 +00:00
2013-06-17 23:36:45 +00:00
self . fTypes = types
2013-06-13 20:02:29 +00:00
return self
def comment ( self , comment ) :
2013-06-19 17:42:17 +00:00
self . fComment = comment
2013-06-13 20:02:29 +00:00
return self
2013-06-11 21:44:08 +00:00
def done ( self ) :
return self . fParent
class PdfClassField :
2013-06-19 17:42:17 +00:00
def __init__ ( self , parent , required , version = ' ' , inheritable = False ) :
2013-06-12 19:07:45 +00:00
#self.fProp = ''
2013-06-11 21:44:08 +00:00
self . fParent = parent
self . fRequired = required
2013-06-13 20:02:29 +00:00
self . fVersion = version
self . fInheritable = inheritable
2013-06-11 21:44:08 +00:00
2013-06-12 19:07:45 +00:00
def field ( self , name , abr = ' ' ) :
self . fProp = PdfField ( self , name , abr )
return self . fProp
2013-06-11 21:44:08 +00:00
def done ( self ) :
return self . fParent
class PdfClass :
2013-06-13 20:02:29 +00:00
def __init__ ( self , name , base , comment ) :
2013-06-11 21:44:08 +00:00
self . fFields = [ ]
self . fIncludes = [ ]
2013-07-10 17:09:50 +00:00
self . fCCPublicNative = [ ]
self . fCCPublicNativeCpp = [ ]
2013-06-11 21:44:08 +00:00
self . fName = name
self . fBase = base
2013-06-13 20:02:29 +00:00
self . fComment = comment
2013-06-11 21:44:08 +00:00
2013-06-11 23:06:16 +00:00
self . fEnumSubclasses = [ ]
self . fEnum = ' !UNDEFINED '
self . fEnumEnd = ' !UNDEFINED '
2013-06-14 19:22:19 +00:00
self . fCheck = ' '
2013-06-11 23:06:16 +00:00
2013-06-14 19:22:19 +00:00
def check ( self , ifCheck ) :
self . fCheck = ifCheck
return self
2013-06-12 19:07:45 +00:00
def required ( self , badDefault ) :
2013-06-11 21:44:08 +00:00
field = PdfClassField ( self , True )
2013-06-12 19:07:45 +00:00
field . fBadDefault = badDefault
2013-06-11 21:44:08 +00:00
self . fFields . append ( field )
return field
def optional ( self ) :
field = PdfClassField ( self , False )
self . fFields . append ( field )
return field
2013-06-13 20:02:29 +00:00
#([Required] [;] [inheritable] [;] [version]; [comments])
# version: PDF [d].[d]
# ; separate props
#inheritable
#version
#required, if
#optional, if
2013-06-11 21:44:08 +00:00
def include ( self , path ) :
self . fIncludes . append ( path )
return self
2013-07-10 17:09:50 +00:00
def carbonCopyPublicNative ( self , cc ) :
self . fCCPublicNative . append ( cc )
2013-06-12 19:07:45 +00:00
return self
2013-07-10 17:09:50 +00:00
def carbonCopyPublicNativeCpp ( self , cc ) :
self . fCCPublicNativeCpp . append ( cc )
2013-06-11 21:44:08 +00:00
return self
2013-07-02 22:42:53 +00:00
2013-06-13 20:02:29 +00:00
def done ( self ) :
return
2013-06-11 21:44:08 +00:00
class PdfClassManager :
def __init__ ( self ) :
2013-06-11 23:06:16 +00:00
self . fClasses = { }
2013-06-12 19:07:45 +00:00
self . fClassesNamesInOrder = [ ]
2013-06-11 21:44:08 +00:00
2013-07-10 17:09:50 +00:00
def addClass ( self , name , base = ' ' , comment = ' ' ) :
if name == ' Dictionary ' :
2013-06-13 20:02:29 +00:00
cls = PdfClass ( name , ' ' , comment )
2013-06-12 19:07:45 +00:00
else :
2013-06-13 20:02:29 +00:00
cls = PdfClass ( name , base , comment )
2013-06-11 23:06:16 +00:00
self . fClasses [ name ] = cls
2013-06-12 19:07:45 +00:00
self . fClassesNamesInOrder . append ( name )
2013-06-11 21:44:08 +00:00
return cls
2013-06-18 22:00:40 +00:00
def writeEnum ( self , fileEnums , enum , enumToCls ) :
fileEnums . write ( ' ' + enum + ' , \n ' )
2013-06-11 23:06:16 +00:00
cls = enumToCls [ enum ]
cls . fEnumSubclasses . sort ( )
cnt = 0
for sub in cls . fEnumSubclasses :
2013-06-18 22:00:40 +00:00
self . writeEnum ( fileEnums , cls . fEnumSubclasses [ cnt ] , enumToCls )
2013-06-11 23:06:16 +00:00
cnt = cnt + 1
if cnt != 0 :
2013-06-18 22:00:40 +00:00
fileEnums . write ( ' ' + cls . fEnumEnd + ' , \n ' )
2013-06-12 19:07:45 +00:00
2013-07-10 17:09:50 +00:00
def writeAsNull ( self , nativeFileClass , cls , enumToCls ) :
nativeFileClass . write ( ' SkPdf ' + cls . fName + ' * as ' + cls . fName + ' () { return (SkPdf ' + cls . fName + ' *)this;} \n ' )
nativeFileClass . write ( ' const SkPdf ' + cls . fName + ' * as ' + cls . fName + ' () const { return (const SkPdf ' + cls . fName + ' *)this;} \n ' )
nativeFileClass . write ( ' \n ' )
2013-06-12 19:07:45 +00:00
cnt = 0
for sub in cls . fEnumSubclasses :
2013-07-10 17:09:50 +00:00
self . writeAsNull ( nativeFileClass , enumToCls [ cls . fEnumSubclasses [ cnt ] ] , enumToCls )
2013-06-12 19:07:45 +00:00
cnt = cnt + 1
2013-07-10 17:09:50 +00:00
def writeAsFoo ( self , nativeFileClass , cls , enumToCls ) :
2013-06-12 19:07:45 +00:00
# TODO(edisonn): add a container, with sections, public, private, default, ...
# the end code will be grouped
# me
2013-07-10 17:09:50 +00:00
nativeFileClass . write ( ' public: \n ' )
2013-07-02 22:42:53 +00:00
2013-07-10 17:09:50 +00:00
nativeFileClass . write ( ' public: \n ' )
nativeFileClass . write ( ' SkPdf ' + cls . fName + ' * as ' + cls . fName + ' () { return this;} \n ' )
nativeFileClass . write ( ' const SkPdf ' + cls . fName + ' * as ' + cls . fName + ' () const { return this;} \n ' )
nativeFileClass . write ( ' \n ' )
2013-06-12 19:07:45 +00:00
2013-07-10 17:09:50 +00:00
if cls . fName == ' Dictionary ' :
2013-06-12 19:07:45 +00:00
cnt = 0
for sub in cls . fEnumSubclasses :
2013-07-10 17:09:50 +00:00
self . writeAsNull ( nativeFileClass , enumToCls [ cls . fEnumSubclasses [ cnt ] ] , enumToCls )
2013-06-12 19:07:45 +00:00
cnt = cnt + 1
2013-07-10 17:09:50 +00:00
if cls . fName != ' Dictionary ' :
nativeFileClass . write ( ' private: \n ' )
2013-06-12 19:07:45 +00:00
base = self . fClasses [ cls . fBase ]
cnt = 0
for sub in base . fEnumSubclasses :
if enumToCls [ base . fEnumSubclasses [ cnt ] ] . fName != cls . fName :
2013-07-10 17:09:50 +00:00
self . writeAsNull ( nativeFileClass , enumToCls [ base . fEnumSubclasses [ cnt ] ] , enumToCls )
2013-06-12 19:07:45 +00:00
cnt = cnt + 1
2013-06-21 21:03:15 +00:00
def determineAllMustBe ( self , cls , field , enumToCls ) :
mustBe = [ ]
for sub in cls . fEnumSubclasses :
mustBe = mustBe + self . determineAllMustBe ( enumToCls [ sub ] , field , enumToCls )
for subField in cls . fFields :
if subField . fProp . fName == field . fProp . fName :
mustBe = mustBe + subField . fProp . fMustBe
# while cls.fBase != '':
# cls = self.fClasses[cls.fBase]
# # TODO(edisonn): bad perf
# for subField in cls.fFields:
# if subField.fProp.fName == field.fProp.fName:
# mustBe = mustBe + subField.fProp.fMustBe
return mustBe
2013-06-11 23:06:16 +00:00
2013-06-11 21:44:08 +00:00
def write ( self ) :
2013-07-10 17:09:50 +00:00
global fileHeadersNative
global fileHeadersNativeCpp
2013-06-17 23:36:45 +00:00
global knowTypes
2013-06-11 23:06:16 +00:00
# generate enum
enumsRoot = [ ]
enumToCls = { }
for name in self . fClasses :
cls = self . fClasses [ name ]
2013-06-18 22:00:40 +00:00
cls . fEnum = ' k ' + name + ' _SkPdfObjectType '
cls . fEnumEnd = ' k ' + name + ' __End_SkPdfObjectType '
2013-07-10 17:09:50 +00:00
fileHeadersNative . write ( ' #include " SkPdf ' + cls . fName + ' _autogen.h " \n ' )
fileHeadersNativeCpp . write ( ' #include " SkPdf ' + cls . fName + ' _autogen.cpp " \n ' )
2013-06-11 23:06:16 +00:00
if cls . fBase != ' ' :
self . fClasses [ cls . fBase ] . fEnumSubclasses . append ( cls . fEnum )
if cls . fBase == ' ' :
enumsRoot . append ( cls . fEnum )
enumToCls [ cls . fEnum ] = cls
enumsRoot . sort ( )
2013-06-12 19:07:45 +00:00
# TODO(edisonn): move each .h in it's own file
# write imports
2013-06-11 23:06:16 +00:00
# write enums
2013-07-02 22:42:53 +00:00
fileEnums = open ( sys . argv [ 1 ] + ' autogen/SkPdfEnums_autogen.h ' , ' w ' )
2013-06-18 22:00:40 +00:00
fileEnums . write ( ' #ifndef __DEFINED__SkPdfEnums \n ' )
fileEnums . write ( ' #define __DEFINED__SkPdfEnums \n ' )
fileEnums . write ( ' \n ' )
fileEnums . write ( ' enum SkPdfObjectType { \n ' )
2013-07-10 17:09:50 +00:00
fileEnums . write ( ' kNone_SkPdfObjectType = 0, \n ' )
2013-06-11 23:06:16 +00:00
for enum in enumsRoot :
2013-06-18 22:00:40 +00:00
self . writeEnum ( fileEnums , enum , enumToCls )
fileEnums . write ( ' }; \n ' )
fileEnums . write ( ' \n ' )
2013-06-12 19:07:45 +00:00
# write forward class declaration
for name in self . fClassesNamesInOrder :
2013-06-18 22:00:40 +00:00
fileEnums . write ( ' class SkPdf ' + name + ' ; \n ' )
fileEnums . write ( ' \n ' )
fileEnums . write ( ' #endif // __DEFINED__SkPdfEnums \n ' )
fileEnums . close ( )
2013-06-12 19:07:45 +00:00
for name in self . fClassesNamesInOrder :
cls = self . fClasses [ name ]
enum = cls . fEnum
2013-07-10 17:09:50 +00:00
nativeFileClass = open ( sys . argv [ 1 ] + ' native/autogen/SkPdf ' + cls . fName + ' _autogen.h ' , ' w ' )
nativeFileClassCpp = open ( sys . argv [ 1 ] + ' native/autogen/SkPdf ' + cls . fName + ' _autogen.cpp ' , ' w ' )
2013-07-02 22:42:53 +00:00
2013-07-10 17:09:50 +00:00
nativeFileClass . write ( ' #ifndef __DEFINED__SkPdf ' + cls . fName + ' \n ' )
nativeFileClass . write ( ' #define __DEFINED__SkPdf ' + cls . fName + ' \n ' )
nativeFileClass . write ( ' \n ' )
2013-07-02 22:42:53 +00:00
2013-07-10 17:09:50 +00:00
nativeFileClassCpp . write ( ' #include " SkPdf ' + cls . fName + ' _autogen.h " \n \n ' )
nativeFileClassCpp . write ( ' \n ' )
2013-07-02 22:42:53 +00:00
if cls . fBase == ' ' :
2013-07-10 17:09:50 +00:00
nativeFileClass . write ( ' #include " stddef.h " \n ' )
nativeFileClass . write ( ' #include <string> \n ' )
nativeFileClass . write ( ' #include " SkPdfEnums_autogen.h " \n ' )
nativeFileClass . write ( ' #include " SkPdfNYI.h " \n ' )
nativeFileClass . write ( ' #include " SkPdfObject.h " \n ' )
nativeFileClass . write ( ' class SkNativeParsedPDF; \n ' )
2013-07-02 22:42:53 +00:00
2013-06-19 17:42:17 +00:00
if cls . fBase != ' ' :
2013-07-10 17:09:50 +00:00
nativeFileClass . write ( ' #include " SkPdf ' + cls . fBase + ' _autogen.h " \n ' )
2013-07-02 22:42:53 +00:00
2013-07-10 17:09:50 +00:00
nativeFileClassCpp . write ( ' #include " SkNativeParsedPDF.h " \n ' )
2013-07-02 22:42:53 +00:00
2013-07-10 17:09:50 +00:00
nativeFileClass . write ( ' \n ' )
2013-06-19 17:42:17 +00:00
if cls . fComment != ' ' :
2013-07-10 17:09:50 +00:00
nativeFileClass . write ( ' // ' + cls . fComment + ' \n ' )
2013-06-18 22:00:40 +00:00
2013-06-12 19:07:45 +00:00
if cls . fBase == ' ' :
2013-07-10 17:09:50 +00:00
nativeFileClass . write ( ' class SkPdf ' + cls . fName + ' : public SkPdfObject { \n ' )
2013-06-12 19:07:45 +00:00
else :
2013-07-10 17:09:50 +00:00
nativeFileClass . write ( ' class SkPdf ' + cls . fName + ' : public SkPdf ' + cls . fBase + ' { \n ' )
2013-06-12 19:07:45 +00:00
2013-07-10 17:09:50 +00:00
self . writeAsFoo ( nativeFileClass , cls , enumToCls )
2013-06-12 19:07:45 +00:00
2013-07-10 17:09:50 +00:00
nativeFileClass . write ( ' public: \n ' )
2013-07-02 22:42:53 +00:00
2013-07-10 17:09:50 +00:00
for cc in cls . fCCPublicNative :
nativeFileClass . write ( ' ' + cc + ' \n ' )
2013-07-02 22:42:53 +00:00
2013-07-10 17:09:50 +00:00
for cc in cls . fCCPublicNativeCpp :
nativeFileClassCpp . write ( cc + ' \n \n ' )
2013-07-02 22:42:53 +00:00
2013-06-12 19:07:45 +00:00
if cls . fBase == ' ' :
2013-07-10 17:09:50 +00:00
nativeFileClass . write ( ' public: \n ' )
2013-07-02 22:42:53 +00:00
# TODO(edisonn): add is valid ?
2013-06-12 19:07:45 +00:00
#check required fieds, also, there should be an internal_valid() manually wrote for complex
# situations
# right now valid return true
2013-07-10 17:09:50 +00:00
# TODO(edisonn): cache the value of valid, have a set of bits that would remember what types are valid for this type
nativeFileClass . write ( ' bool valid() const { return true;} \n ' )
#nativeFileClass.write('\n')
2013-06-17 20:46:27 +00:00
2013-06-12 19:07:45 +00:00
for field in cls . fFields :
prop = field . fProp
if prop . fCppName != ' ' :
2013-06-19 17:42:17 +00:00
lines = prop . fComment . split ( ' \n ' )
if prop . fComment != ' ' and len ( lines ) > 0 :
2013-07-10 17:09:50 +00:00
nativeFileClass . write ( ' /** ' + lines [ 0 ] + ' \n ' )
2013-06-19 17:42:17 +00:00
for line in lines [ 1 : ] :
2013-07-10 17:09:50 +00:00
nativeFileClass . write ( ' * ' + line + ' \n ' )
nativeFileClass . write ( ' **/ \n ' )
2013-06-19 17:42:17 +00:00
2013-06-14 19:22:19 +00:00
if prop . fCppName [ 0 ] == ' [ ' :
2013-07-10 17:09:50 +00:00
nativeFileClass . write ( ' /* \n ' ) # comment code of the atributes that can have any name
nativeFileClassCpp . write ( ' /* \n ' ) # comment code of the atributes that can have any name
2013-06-17 23:36:45 +00:00
if len ( prop . fTypes . split ( ) ) == 1 :
t = prop . fTypes . strip ( )
2013-07-02 22:42:53 +00:00
2013-07-10 23:17:31 +00:00
nativeFileClass . write ( ' ' + knowTypes [ t ] [ 0 ] + ' ' + prop . fCppName + ' (SkNativeParsedPDF* doc); \n ' )
nativeFileClassCpp . write ( ' ' + knowTypes [ t ] [ 0 ] + ' SkPdf ' + cls . fName + ' :: ' + prop . fCppName + ' (SkNativeParsedPDF* doc) { \n ' )
2013-07-10 17:09:50 +00:00
nativeFileClassCpp . write ( ' SkPdfObject* ret = get( \" ' + prop . fName + ' \" , \" ' + prop . fAbr + ' \" ); \n ' )
nativeFileClassCpp . write ( ' if (doc) { ret = doc->resolveReference(ret);} \n ' )
nativeFileClassCpp . write ( ' if ((ret != NULL && ' + knowTypes [ t ] [ 3 ] + ' ) || (doc == NULL && ret != NULL && ret->isReference())) return ' + knowTypes [ t ] [ 1 ] + ' ; \n ' )
2013-07-02 22:42:53 +00:00
2013-07-10 17:09:50 +00:00
if field . fRequired :
nativeFileClassCpp . write ( ' // TODO(edisonn): warn about missing required field, assert for known good pdfs \n ' )
nativeFileClassCpp . write ( ' return ' + knowTypes [ t ] [ 2 ] . toCpp ( ) + ' ; \n ' ) ;
elif prop . fDefault != ' ' :
nativeFileClassCpp . write ( ' return ' + prop . fDefault . toCpp ( ) + ' ; \n ' ) ;
2013-07-02 22:42:53 +00:00
else :
2013-07-10 17:09:50 +00:00
nativeFileClassCpp . write ( ' // TODO(edisonn): warn about missing default value for optional fields \n ' )
nativeFileClassCpp . write ( ' return ' + knowTypes [ t ] [ 2 ] . toCpp ( ) + ' ; \n ' ) ;
2013-07-02 22:42:53 +00:00
2013-07-10 17:09:50 +00:00
nativeFileClassCpp . write ( ' } \n ' )
nativeFileClassCpp . write ( ' \n ' )
2013-06-17 23:36:45 +00:00
else :
for type in prop . fTypes . split ( ) :
t = type . strip ( )
2013-07-02 22:42:53 +00:00
2013-07-10 23:17:31 +00:00
nativeFileClass . write ( ' bool is ' + prop . fCppName + ' A ' + t . title ( ) + ' (SkNativeParsedPDF* doc); \n ' )
2013-07-10 17:09:50 +00:00
2013-07-10 23:17:31 +00:00
nativeFileClassCpp . write ( ' bool SkPdf ' + cls . fName + ' ::is ' + prop . fCppName + ' A ' + t . title ( ) + ' (SkNativeParsedPDF* doc) { \n ' )
2013-07-10 17:09:50 +00:00
nativeFileClassCpp . write ( ' SkPdfObject* ret = get( \" ' + prop . fName + ' \" , \" ' + prop . fAbr + ' \" ); \n ' )
nativeFileClassCpp . write ( ' if (doc) { ret = doc->resolveReference(ret);} \n ' )
nativeFileClassCpp . write ( ' return ret != NULL && ' + knowTypes [ t ] [ 3 ] + ' ; \n ' )
nativeFileClassCpp . write ( ' } \n ' )
nativeFileClassCpp . write ( ' \n ' )
2013-07-10 23:17:31 +00:00
nativeFileClass . write ( ' ' + knowTypes [ t ] [ 0 ] + ' get ' + prop . fCppName + ' As ' + t . title ( ) + ' (SkNativeParsedPDF* doc); \n ' )
nativeFileClassCpp . write ( ' ' + knowTypes [ t ] [ 0 ] + ' SkPdf ' + cls . fName + ' ::get ' + prop . fCppName + ' As ' + t . title ( ) + ' (SkNativeParsedPDF* doc) { \n ' )
2013-07-10 17:09:50 +00:00
nativeFileClassCpp . write ( ' SkPdfObject* ret = get( \" ' + prop . fName + ' \" , \" ' + prop . fAbr + ' \" ); \n ' )
nativeFileClassCpp . write ( ' if (doc) { ret = doc->resolveReference(ret);} \n ' )
nativeFileClassCpp . write ( ' if ((ret != NULL && ' + knowTypes [ t ] [ 3 ] + ' ) || (doc == NULL && ret != NULL && ret->isReference())) return ' + knowTypes [ t ] [ 1 ] + ' ; \n ' )
if field . fRequired :
nativeFileClassCpp . write ( ' // TODO(edisonn): warn about missing required field, assert for known good pdfs \n ' )
nativeFileClassCpp . write ( ' return ' + knowTypes [ t ] [ 2 ] . toCpp ( ) + ' ; \n ' ) ;
elif prop . fDefault != ' ' :
nativeFileClassCpp . write ( ' return ' + prop . fDefault . toCpp ( ) + ' ; \n ' ) ;
2013-07-02 22:42:53 +00:00
else :
2013-07-10 17:09:50 +00:00
nativeFileClassCpp . write ( ' // TODO(edisonn): warn about missing default value for optional fields \n ' )
nativeFileClassCpp . write ( ' return ' + knowTypes [ t ] [ 2 ] . toCpp ( ) + ' ; \n ' ) ;
nativeFileClassCpp . write ( ' } \n ' )
nativeFileClassCpp . write ( ' \n ' )
2013-06-17 23:36:45 +00:00
2013-07-10 17:09:50 +00:00
nativeFileClass . write ( ' bool has_ ' + prop . fCppName + ' () const; \n ' )
nativeFileClassCpp . write ( ' bool SkPdf ' + cls . fName + ' ::has_ ' + prop . fCppName + ' () const { \n ' )
# TODO(edisonn): has_foo() does not check type, add has_valid_foo(), and check that type is expected (e.g. number, string, ...)
nativeFileClassCpp . write ( ' return get( \" ' + prop . fName + ' \" , \" ' + prop . fAbr + ' \" ) != NULL; \n ' )
nativeFileClassCpp . write ( ' } \n ' )
nativeFileClassCpp . write ( ' \n ' )
2013-06-13 20:02:29 +00:00
2013-06-14 19:22:19 +00:00
if prop . fCppName [ 0 ] == ' [ ' :
2013-07-10 17:09:50 +00:00
nativeFileClass . write ( ' */ \n ' ) # comment code of the atributes that can have any name
nativeFileClassCpp . write ( ' */ \n ' ) # comment code of the atributes that can have any name
2013-06-13 20:02:29 +00:00
2013-06-12 19:07:45 +00:00
2013-07-10 17:09:50 +00:00
nativeFileClass . write ( ' }; \n ' )
nativeFileClass . write ( ' \n ' )
2013-06-18 22:00:40 +00:00
2013-07-10 17:09:50 +00:00
nativeFileClass . write ( ' #endif // __DEFINED__NATIVE_SkPdf ' + cls . fName + ' \n ' )
2013-07-02 22:42:53 +00:00
2013-07-10 17:09:50 +00:00
nativeFileClass . close ( )
nativeFileClassCpp . close ( )
2013-06-12 19:07:45 +00:00
# generate constructor when knowing the type
# later, p2, generate constructor when not knowing the type - very similar with parsing?
2013-06-11 23:06:16 +00:00
# generate parser
2013-06-12 19:07:45 +00:00
# TODO(edisonn): fast recognition based on must attributes.
2013-07-10 17:09:50 +00:00
fileMapperNative = open ( sys . argv [ 1 ] + ' native/autogen/SkPdfMapper_autogen.h ' , ' w ' )
fileMapperNativeCpp = open ( sys . argv [ 1 ] + ' native/autogen/SkPdfMapper_autogen.cpp ' , ' w ' )
2013-07-02 22:42:53 +00:00
2013-07-10 17:09:50 +00:00
fileMapperNative . write ( ' #ifndef __DEFINED__SkPdfMapper \n ' )
fileMapperNative . write ( ' #define __DEFINED__SkPdfMapper \n ' )
fileMapperNative . write ( ' \n ' )
2013-07-02 22:42:53 +00:00
2013-07-10 17:09:50 +00:00
fileMapperNative . write ( ' #include " SkPdfHeaders_autogen.h " \n ' )
fileMapperNative . write ( ' #include " SkNativeParsedPDF.h " \n ' )
fileMapperNative . write ( ' #include " SkPdfObject.h " \n ' )
2013-07-02 22:42:53 +00:00
2013-07-10 17:09:50 +00:00
fileMapperNativeCpp . write ( ' #include " SkPdfMapper_autogen.h " \n ' )
fileMapperNativeCpp . write ( ' #include " SkPdfUtils.h " \n ' )
fileMapperNativeCpp . write ( ' #include " SkPdfObject.h " \n ' )
fileMapperNativeCpp . write ( ' \n ' )
2013-07-02 22:42:53 +00:00
2013-07-10 17:09:50 +00:00
fileMapperNative . write ( ' class SkPdfMapper { \n ' )
2013-07-02 22:42:53 +00:00
2013-07-10 23:17:31 +00:00
fileMapperNative . write ( ' SkNativeParsedPDF* fParsedDoc; \n ' )
2013-07-02 22:42:53 +00:00
2013-07-10 17:09:50 +00:00
fileMapperNative . write ( ' public: \n ' )
2013-07-02 22:42:53 +00:00
2013-07-10 23:17:31 +00:00
fileMapperNative . write ( ' SkPdfMapper(SkNativeParsedPDF* doc) : fParsedDoc(doc) {} \n ' )
2013-07-10 17:09:50 +00:00
fileMapperNative . write ( ' \n ' )
2013-07-02 22:42:53 +00:00
2013-06-12 19:07:45 +00:00
for name in self . fClassesNamesInOrder :
cls = self . fClasses [ name ]
2013-07-10 17:09:50 +00:00
fileMapperNative . write ( ' SkPdfObjectType map ' + name + ' (const SkPdfObject* in) const; \n ' )
2013-06-17 20:46:27 +00:00
2013-07-10 17:09:50 +00:00
fileMapperNativeCpp . write ( ' SkPdfObjectType SkPdfMapper::map ' + name + ' (const SkPdfObject* in) const { \n ' )
fileMapperNativeCpp . write ( ' if (!is ' + name + ' (in)) return kNone_SkPdfObjectType; \n ' )
fileMapperNativeCpp . write ( ' \n ' )
if len ( cls . fEnumSubclasses ) > 0 :
fileMapperNativeCpp . write ( ' SkPdfObjectType ret; \n ' )
2013-06-21 21:03:15 +00:00
# stream must be last one
hasStream = False
2013-06-12 19:07:45 +00:00
for sub in cls . fEnumSubclasses :
2013-07-10 17:09:50 +00:00
fileMapperNativeCpp . write ( ' if (kNone_SkPdfObjectType != (ret = map ' + enumToCls [ sub ] . fName + ' (in))) return ret; \n ' )
2013-06-21 21:03:15 +00:00
2013-07-10 17:09:50 +00:00
fileMapperNativeCpp . write ( ' \n ' )
2013-06-12 19:07:45 +00:00
2013-07-10 17:09:50 +00:00
fileMapperNativeCpp . write ( ' return k ' + name + ' _SkPdfObjectType; \n ' )
fileMapperNativeCpp . write ( ' } \n ' )
fileMapperNativeCpp . write ( ' \n ' )
2013-06-12 19:07:45 +00:00
for name in self . fClassesNamesInOrder :
cls = self . fClasses [ name ]
2013-07-10 17:09:50 +00:00
fileMapperNative . write ( ' bool is ' + name + ' (const SkPdfObject* nativeObj) const ; \n ' )
fileMapperNativeCpp . write ( ' bool SkPdfMapper::is ' + name + ' (const SkPdfObject* nativeObj) const { \n ' )
2013-06-12 19:07:45 +00:00
2013-06-14 19:22:19 +00:00
if cls . fCheck != ' ' :
2013-07-10 17:09:50 +00:00
fileMapperNativeCpp . write ( ' return ' + cls . fCheck + ' ; \n ' )
2013-06-12 19:07:45 +00:00
else :
2013-06-14 19:22:19 +00:00
cntMust = 0
2013-07-10 17:09:50 +00:00
emitedRet = False
2013-06-14 19:22:19 +00:00
for field in cls . fFields :
prop = field . fProp
if prop . fHasMust :
2013-07-10 17:09:50 +00:00
if emitedRet == False :
fileMapperNativeCpp . write ( ' const SkPdfObject* ret = NULL; \n ' )
emitedRet = True
2013-06-14 19:22:19 +00:00
cntMust = cntMust + 1
2013-07-10 17:09:50 +00:00
fileMapperNativeCpp . write ( ' if (!nativeObj->isDictionary()) return false; \n ' )
fileMapperNativeCpp . write ( ' ret = nativeObj->get( \" ' + prop . fName + ' \" , \" ' + prop . fAbr + ' \" ); \n ' )
fileMapperNativeCpp . write ( ' if (ret == NULL) return false; \n ' )
2013-06-21 21:03:15 +00:00
eval = ' ' ;
# TODO(edisonn): this could get out of hand, and could have poor performance if continued on this path
# but if we would write our parser, then best thing would be to create a map of (key, value) -> to bits
# and at each (key, value) we do an and with the bits existent, then we check what bits are left, which would tell the posible types of this dictionary
# and for non unique posinilities (if any) based on context, or the requester of dictionry we can determine fast the dictionary type
mustBe = self . determineAllMustBe ( cls , field , enumToCls )
if len ( mustBe ) > 0 :
for cnd in mustBe :
if eval == ' ' :
2013-07-10 17:09:50 +00:00
eval = ' ( ' + knowTypes [ prop . fTypes . strip ( ) ] [ 1 ] + ' != ' + cnd . toCpp ( ) + ' ) '
2013-06-21 21:03:15 +00:00
else :
2013-07-10 17:09:50 +00:00
eval = eval + ' && ' + ' ( ' + knowTypes [ prop . fTypes . strip ( ) ] [ 1 ] + ' != ' + cnd . toCpp ( ) + ' ) '
fileMapperNativeCpp . write ( ' if ( ' + eval + ' ) return false; \n ' )
fileMapperNativeCpp . write ( ' \n ' )
2013-06-14 19:22:19 +00:00
2013-07-10 17:09:50 +00:00
fileMapperNativeCpp . write ( ' return true; \n ' )
2013-06-12 19:07:45 +00:00
2013-07-10 17:09:50 +00:00
fileMapperNativeCpp . write ( ' } \n ' )
fileMapperNativeCpp . write ( ' \n ' )
2013-06-12 19:07:45 +00:00
2013-07-10 17:09:50 +00:00
# TODO(edisonn): dict should be a SkPdfDictionary ?
fileMapperNative . write ( ' bool SkPdf ' + name + ' FromDictionary(const SkPdfObject* dict, const char* key, SkPdf ' + name + ' ** data) const ; \n ' )
fileMapperNativeCpp . write ( ' bool SkPdfMapper::SkPdf ' + name + ' FromDictionary(const SkPdfObject* dict, const char* key, SkPdf ' + name + ' ** data) const { \n ' )
fileMapperNativeCpp . write ( ' const SkPdfObject* value = dict->get(key); \n ' )
fileMapperNativeCpp . write ( ' if (value == NULL) { return false; } \n ' )
fileMapperNativeCpp . write ( ' if (data == NULL) { return true; } \n ' )
fileMapperNativeCpp . write ( ' if (kNone_SkPdfObjectType == map ' + name + ' (value)) return false; \n ' )
fileMapperNativeCpp . write ( ' *data = (SkPdf ' + name + ' *)value; \n ' )
fileMapperNativeCpp . write ( ' return true; \n ' ) ;
fileMapperNativeCpp . write ( ' } \n ' )
fileMapperNativeCpp . write ( ' \n ' )
fileMapperNative . write ( ' bool SkPdf ' + name + ' FromDictionary(const SkPdfObject* dict, const char* key, const char* abr, SkPdf ' + name + ' ** data) const ; \n ' )
fileMapperNativeCpp . write ( ' bool SkPdfMapper::SkPdf ' + name + ' FromDictionary(const SkPdfObject* dict, const char* key, const char* abr, SkPdf ' + name + ' ** data) const { \n ' )
fileMapperNativeCpp . write ( ' if (SkPdf ' + name + ' FromDictionary(dict, key, data)) return true; \n ' )
fileMapperNativeCpp . write ( ' if (abr == NULL || *abr == \' \\ 0 \' ) return false; \n ' )
fileMapperNativeCpp . write ( ' return SkPdf ' + name + ' FromDictionary(dict, abr, data); \n ' )
fileMapperNativeCpp . write ( ' } \n ' )
fileMapperNativeCpp . write ( ' \n ' )
2013-06-26 17:48:12 +00:00
2013-07-10 17:09:50 +00:00
fileMapperNative . write ( ' }; \n ' )
fileMapperNative . write ( ' \n ' )
2013-06-18 22:00:40 +00:00
2013-07-10 17:09:50 +00:00
fileMapperNative . write ( ' #endif // __DEFINED__SkPdfMapper \n ' )
2013-07-02 22:42:53 +00:00
2013-07-10 17:09:50 +00:00
fileMapperNative . close ( )
fileMapperNativeCpp . close ( )
2013-06-12 19:07:45 +00:00
2013-06-11 21:44:08 +00:00
return
def generateCode ( ) :
2013-07-10 17:09:50 +00:00
global fileHeadersNative
global fileHeadersNativeCpp
2013-06-25 20:45:40 +00:00
global knowTypes
2013-06-18 22:00:40 +00:00
2013-07-10 17:09:50 +00:00
fileHeadersNative = open ( sys . argv [ 1 ] + ' native/autogen/SkPdfHeaders_autogen.h ' , ' w ' )
fileHeadersNativeCpp = open ( sys . argv [ 1 ] + ' native/autogen/SkPdfHeaders_autogen.cpp ' , ' w ' )
2013-06-18 22:00:40 +00:00
2013-07-10 17:09:50 +00:00
fileHeadersNative . write ( ' #ifndef __DEFINED__SkPdfHeaders \n ' )
fileHeadersNative . write ( ' #define __DEFINED__SkPdfHeaders \n ' )
fileHeadersNative . write ( ' \n ' )
2013-06-18 22:00:40 +00:00
2013-07-10 17:09:50 +00:00
fileHeadersNativeCpp . write ( ' #include " SkPdfHeaders_autogen.h " \n ' )
2013-06-26 17:48:12 +00:00
2013-06-14 19:22:19 +00:00
manager = PdfClassManager ( )
# these classes are not explicitely backed by a table in the pdf spec
2013-07-10 17:09:50 +00:00
manager . addClass ( ' Dictionary ' )
2013-06-14 19:22:19 +00:00
manager . addClass ( ' XObjectDictionary ' , ' Dictionary ' )
manager . addClass ( ' FontDictionary ' , ' Dictionary ' )
2013-06-11 21:44:08 +00:00
2013-06-21 21:03:15 +00:00
manager . addClass ( ' TrueTypeFontDictionary ' , ' Type1FontDictionary ' ) \
. required ( ' NULL ' ) \
. field ( ' Subtype ' ) \
. name ( ' Subtype ' ) \
. type ( ' name ' ) \
. comment ( ' ' ) \
. must ( [ datatypes . PdfName ( ' TrueType ' ) ] ) \
. done ( ) . done ( ) \
2013-06-11 21:44:08 +00:00
2013-06-25 20:45:40 +00:00
addDictionaryTypesTo ( knowTypes )
buildPdfSpec ( manager )
2013-06-14 19:22:19 +00:00
manager . addClass ( ' MultiMasterFontDictionary ' , ' Type1FontDictionary ' ) \
. required ( ' NULL ' ) \
. field ( ' Subtype ' ) \
. name ( ' Subtype ' ) \
2013-06-13 20:02:29 +00:00
. type ( ' name ' ) \
2013-06-14 19:22:19 +00:00
. comment ( ' ' ) \
2013-06-21 21:03:15 +00:00
. must ( [ datatypes . PdfName ( ' MMType1 ' ) ] ) \
2013-06-13 20:02:29 +00:00
. done ( ) . done ( ) \
2013-06-14 19:22:19 +00:00
manager . write ( )
2013-06-11 21:44:08 +00:00
2013-07-10 17:09:50 +00:00
fileHeadersNative . write ( ' #endif // __DEFINED__SkPdfHeaders \n ' )
2013-07-02 22:42:53 +00:00
2013-07-10 17:09:50 +00:00
fileHeadersNative . close ( )
fileHeadersNativeCpp . close ( )
2013-06-11 21:44:08 +00:00
if ' __main__ ' == __name__ :
2013-07-02 22:42:53 +00:00
#print sys.argv
2013-06-11 21:44:08 +00:00
sys . exit ( generateCode ( ) )
2013-06-13 20:02:29 +00:00