blob: 51fa173cd1e4d040954cfe72caf06b68144fe52e [file] [log] [blame]
edisonn@google.coma2fab9d2013-06-14 19:22:19 +00001
2
edisonn@google.com1a191c62013-06-11 21:44:08 +00003import sys
4
edisonn@google.coma2fab9d2013-06-14 19:22:19 +00005import datatypes
edisonn@google.comb857a0c2013-06-25 20:45:40 +00006from autogen.pdfspec_autogen import *
edisonn@google.comaf3daa02013-06-12 19:07:45 +00007
edisonn@google.com571c70b2013-07-10 17:09:50 +00008# TODO(edisonn): date and some other types are in fact strings, with a custom format!!!
9# TODO(edisonn): refer to page 99 (PDF data types)
edisonn@google.com1277cf02013-06-17 23:36:45 +000010knowTypes = {
edisonn@google.com571c70b2013-07-10 17:09:50 +000011'(any)': ['SkPdfObject*', 'ret', datatypes.CppNull(), 'true', 'use a mapper'],
12# TODO(edisonn): return constant for undefined
13'(undefined)': ['SkPdfObject*', 'ret', datatypes.CppNull(), 'true', 'use a mapper'],
14'(various)': ['SkPdfObject*', 'ret', datatypes.CppNull(), 'true', 'use a mapper'],
15'array': ['SkPdfArray*', '(SkPdfArray*)ret', datatypes.CppNull(), 'ret->isArray()'],
16'boolean': ['bool', 'ret->boolValue()', datatypes.PdfBoolean('false'), 'ret->isBoolean()'],
17#date is a string, with special formating, add here the
18'date': ['SkPdfDate', 'ret->dateValue()', datatypes.PdfDateNever(), 'ret->isDate()'],
19'dictionary': ['SkPdfDictionary*', '(SkPdfDictionary*)ret', datatypes.CppNull(), 'ret->isDictionary()', 'use a mapper'],
20'function': ['SkPdfFunction', 'ret->functionValue()', datatypes.PdfFunctionNone(), 'ret->isFunction()'],
21'integer': ['int64_t', 'ret->intValue()', datatypes.PdfInteger(0), 'ret->isInteger()'],
22'file_specification': ['SkPdfFileSpec', 'ret->fileSpecValue()', datatypes.FileSpecNone(), 'false'],
23'name': ['std::string', 'ret->nameValue2()', datatypes.PdfString('""'), 'ret->isName()'],
24#should assert, references should never be allowed here, should be resolved way earlier
25'tree': ['SkPdfTree', 'ret->treeValue()', datatypes.EmptyTree(), 'false'],
26'number': ['double', 'ret->numberValue()', datatypes.PdfNumber(0), 'ret->isNumber()'],
27'rectangle': ['SkRect', 'ret->rectangleValue()', datatypes.EmptyRect(), 'ret->isRectangle()'],
28'stream': ['SkPdfStream*', 'ret->getStream()', datatypes.CppNull(), 'ret->hasStream()'],
29'string': ['std::string', 'ret->stringValue2()', datatypes.PdfString('""'), 'ret->isAnyString()'],
30'text': ['std::string', 'ret->stringValue2()', datatypes.PdfString('""'), 'ret->isAnyString()'],
31'text string': ['std::string', 'ret->stringValue2()', datatypes.PdfString('""'), 'ret->isAnyString()'],
32'matrix': ['SkMatrix', 'ret->matrixValue()', datatypes.IdentityMatrix(), 'ret->isMatrix()'],
edisonn@google.com1277cf02013-06-17 23:36:45 +000033}
edisonn@google.com45327112013-06-13 20:02:29 +000034
35
edisonn@google.com1a191c62013-06-11 21:44:08 +000036class PdfField:
37 def __init__(self, parent, name, abr):
38 self.fParent = parent
39 self.fName = name
40 self.fAbr = abr
41
42 self.fDefault = ''
edisonn@google.com1277cf02013-06-17 23:36:45 +000043 self.fTypes = ''
edisonn@google.comaf3daa02013-06-12 19:07:45 +000044 self.fCppName = ''
edisonn@google.com1277cf02013-06-17 23:36:45 +000045 self.fEnumValues = []
46 self.fHasMust = False
edisonn@google.comff278442013-06-21 21:03:15 +000047 self.fMustBe = []
edisonn@google.comafe5e9e2013-06-19 17:42:17 +000048 self.fComment = ''
edisonn@google.com1a191c62013-06-11 21:44:08 +000049
50 def must(self, value):
edisonn@google.comaf3daa02013-06-12 19:07:45 +000051 self.fHasMust = True
52 self.fMustBe = value
53 return self
edisonn@google.com1a191c62013-06-11 21:44:08 +000054
55 def default(self, value):
56 self.fDefault = value
57 return self
58
edisonn@google.com1277cf02013-06-17 23:36:45 +000059 def multiple(self, enumValues):
60 self.fEnumValues = enumValues
edisonn@google.com1a191c62013-06-11 21:44:08 +000061 return self
62
edisonn@google.comaf3daa02013-06-12 19:07:45 +000063 def name(self, name):
edisonn@google.comaf3daa02013-06-12 19:07:45 +000064 self.fCppName = name
edisonn@google.com1a191c62013-06-11 21:44:08 +000065 return self
66
edisonn@google.com1277cf02013-06-17 23:36:45 +000067 def type(self, types):
edisonn@google.com45327112013-06-13 20:02:29 +000068 # TODO (edisonn): if simple type, use it, otherwise set it to Dictionary, and set a mask for valid types, like array or name
edisonn@google.com1277cf02013-06-17 23:36:45 +000069 types = types.strip()
edisonn@google.com6e49c342013-06-27 20:03:43 +000070 types = types.replace(' or ', ' ')
71 types = types.replace(' or,', ' ')
72 types = types.replace(',or ', ' ')
73 types = types.replace(',or,', ' ')
edisonn@google.com1277cf02013-06-17 23:36:45 +000074 types = types.replace(',', ' ')
75 types = types.replace('text', ' ') # TODO(edisonn): what is the difference between 'text string' and 'string'?
76 types = types.replace('file specification', 'file_specification')
edisonn@google.coma2fab9d2013-06-14 19:22:19 +000077
edisonn@google.coma2fab9d2013-06-14 19:22:19 +000078
edisonn@google.com1277cf02013-06-17 23:36:45 +000079 self.fTypes = types
edisonn@google.com45327112013-06-13 20:02:29 +000080 return self
81
82 def comment(self, comment):
edisonn@google.comafe5e9e2013-06-19 17:42:17 +000083 self.fComment = comment
edisonn@google.com45327112013-06-13 20:02:29 +000084 return self
85
edisonn@google.com1a191c62013-06-11 21:44:08 +000086 def done(self):
87 return self.fParent
88
89
90class PdfClassField:
edisonn@google.comafe5e9e2013-06-19 17:42:17 +000091 def __init__(self, parent, required, version='', inheritable=False):
edisonn@google.comaf3daa02013-06-12 19:07:45 +000092 #self.fProp = ''
edisonn@google.com1a191c62013-06-11 21:44:08 +000093 self.fParent = parent
94 self.fRequired = required
edisonn@google.com45327112013-06-13 20:02:29 +000095 self.fVersion = version
96 self.fInheritable = inheritable
edisonn@google.com1a191c62013-06-11 21:44:08 +000097
edisonn@google.comaf3daa02013-06-12 19:07:45 +000098 def field(self, name, abr=''):
99 self.fProp = PdfField(self, name, abr)
100 return self.fProp
edisonn@google.com1a191c62013-06-11 21:44:08 +0000101
102 def done(self):
103 return self.fParent
104
105class PdfClass:
edisonn@google.com45327112013-06-13 20:02:29 +0000106 def __init__(self, name, base, comment):
edisonn@google.com1a191c62013-06-11 21:44:08 +0000107 self.fFields = []
108 self.fIncludes = []
edisonn@google.com571c70b2013-07-10 17:09:50 +0000109 self.fCCPublicNative = []
110 self.fCCPublicNativeCpp = []
edisonn@google.com1a191c62013-06-11 21:44:08 +0000111 self.fName = name
112 self.fBase = base
edisonn@google.com45327112013-06-13 20:02:29 +0000113 self.fComment = comment
edisonn@google.com1a191c62013-06-11 21:44:08 +0000114
edisonn@google.comf7dd4912013-06-11 23:06:16 +0000115 self.fEnumSubclasses = []
116
117 self.fEnum = '!UNDEFINED'
118 self.fEnumEnd = '!UNDEFINED'
edisonn@google.coma2fab9d2013-06-14 19:22:19 +0000119 self.fCheck = ''
edisonn@google.comf7dd4912013-06-11 23:06:16 +0000120
edisonn@google.coma2fab9d2013-06-14 19:22:19 +0000121 def check(self, ifCheck):
122 self.fCheck = ifCheck
123 return self
124
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000125 def required(self, badDefault):
edisonn@google.com1a191c62013-06-11 21:44:08 +0000126 field = PdfClassField(self, True)
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000127 field.fBadDefault = badDefault
edisonn@google.com1a191c62013-06-11 21:44:08 +0000128 self.fFields.append(field)
129 return field
130
131 def optional(self):
132 field = PdfClassField(self, False)
133 self.fFields.append(field)
134 return field
edisonn@google.com45327112013-06-13 20:02:29 +0000135
136 #([Required] [;] [inheritable] [;] [version]; [comments])
137 # version: PDF [d].[d]
138 # ; separate props
139 #inheritable
140 #version
141 #required, if
142 #optional, if
edisonn@google.com1a191c62013-06-11 21:44:08 +0000143
144 def include(self, path):
145 self.fIncludes.append(path)
146 return self
147
edisonn@google.com571c70b2013-07-10 17:09:50 +0000148 def carbonCopyPublicNative(self, cc):
149 self.fCCPublicNative.append(cc)
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000150 return self
151
edisonn@google.com571c70b2013-07-10 17:09:50 +0000152 def carbonCopyPublicNativeCpp(self, cc):
153 self.fCCPublicNativeCpp.append(cc)
edisonn@google.com1a191c62013-06-11 21:44:08 +0000154 return self
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000155
edisonn@google.com45327112013-06-13 20:02:29 +0000156 def done(self):
157 return
edisonn@google.com1a191c62013-06-11 21:44:08 +0000158
159class PdfClassManager:
160 def __init__(self):
edisonn@google.comf7dd4912013-06-11 23:06:16 +0000161 self.fClasses = {}
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000162 self.fClassesNamesInOrder = []
edisonn@google.com1a191c62013-06-11 21:44:08 +0000163
edisonn@google.com571c70b2013-07-10 17:09:50 +0000164 def addClass(self, name, base='', comment=''):
165 if name == 'Dictionary':
edisonn@google.com45327112013-06-13 20:02:29 +0000166 cls = PdfClass(name, '', comment)
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000167 else:
edisonn@google.com45327112013-06-13 20:02:29 +0000168 cls = PdfClass(name, base, comment)
edisonn@google.comf7dd4912013-06-11 23:06:16 +0000169 self.fClasses[name] = cls
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000170 self.fClassesNamesInOrder.append(name)
edisonn@google.com1a191c62013-06-11 21:44:08 +0000171 return cls
172
edisonn@google.com59543d32013-06-18 22:00:40 +0000173 def writeEnum(self, fileEnums, enum, enumToCls):
174 fileEnums.write(' ' + enum + ',\n')
edisonn@google.comf7dd4912013-06-11 23:06:16 +0000175 cls = enumToCls[enum]
176 cls.fEnumSubclasses.sort()
177
178 cnt = 0
179 for sub in cls.fEnumSubclasses:
edisonn@google.com59543d32013-06-18 22:00:40 +0000180 self.writeEnum(fileEnums, cls.fEnumSubclasses[cnt], enumToCls)
edisonn@google.comf7dd4912013-06-11 23:06:16 +0000181 cnt = cnt + 1
182
183 if cnt != 0:
edisonn@google.com59543d32013-06-18 22:00:40 +0000184 fileEnums.write(' ' + cls.fEnumEnd + ',\n')
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000185
186
edisonn@google.com571c70b2013-07-10 17:09:50 +0000187 def writeAsNull(self, nativeFileClass, cls, enumToCls):
188 nativeFileClass.write(' SkPdf' + cls.fName +'* as' + cls.fName + '() {return (SkPdf' + cls.fName + '*)this;}\n')
189 nativeFileClass.write(' const SkPdf' + cls.fName +'* as' + cls.fName + '() const {return (const SkPdf' + cls.fName + '*)this;}\n')
190 nativeFileClass.write('\n')
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000191
192 cnt = 0
193 for sub in cls.fEnumSubclasses:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000194 self.writeAsNull(nativeFileClass, enumToCls[cls.fEnumSubclasses[cnt]], enumToCls)
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000195 cnt = cnt + 1
196
197
edisonn@google.com571c70b2013-07-10 17:09:50 +0000198 def writeAsFoo(self, nativeFileClass, cls, enumToCls):
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000199 # TODO(edisonn): add a container, with sections, public, private, default, ...
200 # the end code will be grouped
201
202 # me
edisonn@google.com571c70b2013-07-10 17:09:50 +0000203 nativeFileClass.write('public:\n')
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000204
edisonn@google.com571c70b2013-07-10 17:09:50 +0000205 nativeFileClass.write('public:\n')
206 nativeFileClass.write(' SkPdf' + cls.fName +'* as' + cls.fName + '() {return this;}\n')
207 nativeFileClass.write(' const SkPdf' + cls.fName +'* as' + cls.fName + '() const {return this;}\n')
208 nativeFileClass.write('\n')
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000209
edisonn@google.com571c70b2013-07-10 17:09:50 +0000210 if cls.fName == 'Dictionary':
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000211 cnt = 0
212 for sub in cls.fEnumSubclasses:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000213 self.writeAsNull(nativeFileClass, enumToCls[cls.fEnumSubclasses[cnt]], enumToCls)
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000214 cnt = cnt + 1
215
edisonn@google.com571c70b2013-07-10 17:09:50 +0000216 if cls.fName != 'Dictionary':
217 nativeFileClass.write('private:\n')
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000218 base = self.fClasses[cls.fBase]
219 cnt = 0
220 for sub in base.fEnumSubclasses:
221 if enumToCls[base.fEnumSubclasses[cnt]].fName != cls.fName:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000222 self.writeAsNull(nativeFileClass, enumToCls[base.fEnumSubclasses[cnt]], enumToCls)
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000223 cnt = cnt + 1
224
225
edisonn@google.comff278442013-06-21 21:03:15 +0000226 def determineAllMustBe(self, cls, field, enumToCls):
227 mustBe = []
228 for sub in cls.fEnumSubclasses:
229 mustBe = mustBe + self.determineAllMustBe(enumToCls[sub], field, enumToCls)
230
231 for subField in cls.fFields:
232 if subField.fProp.fName == field.fProp.fName:
233 mustBe = mustBe + subField.fProp.fMustBe
234
235# while cls.fBase != '':
236# cls = self.fClasses[cls.fBase]
237# # TODO(edisonn): bad perf
238# for subField in cls.fFields:
239# if subField.fProp.fName == field.fProp.fName:
240# mustBe = mustBe + subField.fProp.fMustBe
241
242 return mustBe
edisonn@google.comf7dd4912013-06-11 23:06:16 +0000243
edisonn@google.com1a191c62013-06-11 21:44:08 +0000244 def write(self):
edisonn@google.com571c70b2013-07-10 17:09:50 +0000245 global fileHeadersNative
246 global fileHeadersNativeCpp
edisonn@google.com1277cf02013-06-17 23:36:45 +0000247 global knowTypes
248
edisonn@google.comf7dd4912013-06-11 23:06:16 +0000249 # generate enum
250 enumsRoot = []
251
252 enumToCls = {}
253
254 for name in self.fClasses:
255 cls = self.fClasses[name]
edisonn@google.com59543d32013-06-18 22:00:40 +0000256 cls.fEnum = 'k' + name + '_SkPdfObjectType'
257 cls.fEnumEnd = 'k' + name + '__End_SkPdfObjectType'
258
edisonn@google.com571c70b2013-07-10 17:09:50 +0000259 fileHeadersNative.write('#include "SkPdf' + cls.fName + '_autogen.h"\n')
260 fileHeadersNativeCpp.write('#include "SkPdf' + cls.fName + '_autogen.cpp"\n')
edisonn@google.comf7dd4912013-06-11 23:06:16 +0000261
262 if cls.fBase != '':
263 self.fClasses[cls.fBase].fEnumSubclasses.append(cls.fEnum)
264
265 if cls.fBase == '':
266 enumsRoot.append(cls.fEnum)
267
268 enumToCls[cls.fEnum] = cls
269
270 enumsRoot.sort()
271
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000272
273 # TODO(edisonn): move each .h in it's own file
274 # write imports
275
edisonn@google.comf7dd4912013-06-11 23:06:16 +0000276 # write enums
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000277 fileEnums = open(sys.argv[1] + 'autogen/SkPdfEnums_autogen.h', 'w')
edisonn@google.com59543d32013-06-18 22:00:40 +0000278 fileEnums.write('#ifndef __DEFINED__SkPdfEnums\n')
279 fileEnums.write('#define __DEFINED__SkPdfEnums\n')
280 fileEnums.write('\n')
281
282 fileEnums.write('enum SkPdfObjectType {\n')
edisonn@google.com571c70b2013-07-10 17:09:50 +0000283 fileEnums.write(' kNone_SkPdfObjectType = 0,\n')
edisonn@google.comf7dd4912013-06-11 23:06:16 +0000284 for enum in enumsRoot:
edisonn@google.com59543d32013-06-18 22:00:40 +0000285 self.writeEnum(fileEnums, enum, enumToCls)
286 fileEnums.write('};\n')
287 fileEnums.write('\n')
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000288
289 # write forward class declaration
290 for name in self.fClassesNamesInOrder:
edisonn@google.com59543d32013-06-18 22:00:40 +0000291 fileEnums.write('class SkPdf' + name + ';\n')
292 fileEnums.write('\n')
293
294 fileEnums.write('#endif // __DEFINED__SkPdfEnums\n')
295 fileEnums.close()
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000296
297 for name in self.fClassesNamesInOrder:
298 cls = self.fClasses[name]
299 enum = cls.fEnum
edisonn@google.comf7dd4912013-06-11 23:06:16 +0000300
edisonn@google.com571c70b2013-07-10 17:09:50 +0000301 nativeFileClass = open(sys.argv[1] + 'native/autogen/SkPdf' + cls.fName + '_autogen.h', 'w')
302 nativeFileClassCpp = open(sys.argv[1] + 'native/autogen/SkPdf' + cls.fName + '_autogen.cpp', 'w')
edisonn@google.com59543d32013-06-18 22:00:40 +0000303
edisonn@google.com571c70b2013-07-10 17:09:50 +0000304 nativeFileClass.write('#ifndef __DEFINED__SkPdf' + cls.fName + '\n')
305 nativeFileClass.write('#define __DEFINED__SkPdf' + cls.fName + '\n')
306 nativeFileClass.write('\n')
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000307
edisonn@google.com571c70b2013-07-10 17:09:50 +0000308 nativeFileClassCpp.write('#include "SkPdf' + cls.fName + '_autogen.h"\n\n')
309 nativeFileClassCpp.write('\n')
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000310
311
312 if cls.fBase == '':
edisonn@google.com571c70b2013-07-10 17:09:50 +0000313 nativeFileClass.write('#include "stddef.h"\n')
314 nativeFileClass.write('#include <string>\n')
315 nativeFileClass.write('#include "SkPdfEnums_autogen.h"\n')
316 nativeFileClass.write('#include "SkPdfNYI.h"\n')
317 nativeFileClass.write('#include "SkPdfObject.h"\n')
318 nativeFileClass.write('class SkNativeParsedPDF;\n')
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000319
edisonn@google.comafe5e9e2013-06-19 17:42:17 +0000320 if cls.fBase != '':
edisonn@google.com571c70b2013-07-10 17:09:50 +0000321 nativeFileClass.write('#include "SkPdf' + cls.fBase + '_autogen.h"\n')
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000322
edisonn@google.com571c70b2013-07-10 17:09:50 +0000323 nativeFileClassCpp.write('#include "SkNativeParsedPDF.h"\n')
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000324
edisonn@google.com571c70b2013-07-10 17:09:50 +0000325
326 nativeFileClass.write('\n')
edisonn@google.comafe5e9e2013-06-19 17:42:17 +0000327
328 if cls.fComment != '':
edisonn@google.com571c70b2013-07-10 17:09:50 +0000329 nativeFileClass.write('// ' + cls.fComment + '\n')
edisonn@google.com59543d32013-06-18 22:00:40 +0000330
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000331 if cls.fBase == '':
edisonn@google.com571c70b2013-07-10 17:09:50 +0000332 nativeFileClass.write('class SkPdf' + cls.fName + ' : public SkPdfObject {\n')
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000333 else:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000334 nativeFileClass.write('class SkPdf' + cls.fName + ' : public SkPdf' + cls.fBase + ' {\n')
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000335
edisonn@google.com571c70b2013-07-10 17:09:50 +0000336 self.writeAsFoo(nativeFileClass, cls, enumToCls)
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000337
edisonn@google.com571c70b2013-07-10 17:09:50 +0000338 nativeFileClass.write('public:\n')
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000339
edisonn@google.com571c70b2013-07-10 17:09:50 +0000340 for cc in cls.fCCPublicNative:
341 nativeFileClass.write(' ' + cc + '\n')
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000342
edisonn@google.com571c70b2013-07-10 17:09:50 +0000343 for cc in cls.fCCPublicNativeCpp:
344 nativeFileClassCpp.write(cc + '\n\n')
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000345
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000346
347 if cls.fBase == '':
edisonn@google.com571c70b2013-07-10 17:09:50 +0000348 nativeFileClass.write('public:\n')
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000349
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000350 # TODO(edisonn): add is valid ?
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000351 #check required fieds, also, there should be an internal_valid() manually wrote for complex
352 # situations
353 # right now valid return true
edisonn@google.com571c70b2013-07-10 17:09:50 +0000354 # TODO(edisonn): cache the value of valid, have a set of bits that would remember what types are valid for this type
355 nativeFileClass.write(' bool valid() const {return true;}\n')
356 #nativeFileClass.write('\n')
edisonn@google.com68d15c82013-06-17 20:46:27 +0000357
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000358 for field in cls.fFields:
359 prop = field.fProp
360 if prop.fCppName != '':
edisonn@google.comafe5e9e2013-06-19 17:42:17 +0000361
362 lines = prop.fComment.split('\n')
363 if prop.fComment != '' and len(lines) > 0:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000364 nativeFileClass.write('/** ' + lines[0] + '\n')
edisonn@google.comafe5e9e2013-06-19 17:42:17 +0000365 for line in lines[1:]:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000366 nativeFileClass.write(' * ' + line + '\n')
367 nativeFileClass.write('**/\n')
edisonn@google.comafe5e9e2013-06-19 17:42:17 +0000368
edisonn@google.coma2fab9d2013-06-14 19:22:19 +0000369 if prop.fCppName[0] == '[':
edisonn@google.com571c70b2013-07-10 17:09:50 +0000370 nativeFileClass.write('/*\n') # comment code of the atributes that can have any name
371 nativeFileClassCpp.write('/*\n') # comment code of the atributes that can have any name
edisonn@google.com1277cf02013-06-17 23:36:45 +0000372
edisonn@google.com1277cf02013-06-17 23:36:45 +0000373
374 if len(prop.fTypes.split()) == 1:
375 t = prop.fTypes.strip()
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000376
edisonn@google.com571c70b2013-07-10 17:09:50 +0000377 nativeFileClass.write(' ' + knowTypes[t][0] + ' ' + prop.fCppName + '(const SkNativeParsedPDF* doc);\n')
378 nativeFileClassCpp.write('' + knowTypes[t][0] + ' SkPdf' + cls.fName + '::' + prop.fCppName + '(const SkNativeParsedPDF* doc) {\n')
379 nativeFileClassCpp.write(' SkPdfObject* ret = get(\"' + prop.fName + '\", \"' + prop.fAbr + '\");\n')
380 nativeFileClassCpp.write(' if (doc) {ret = doc->resolveReference(ret);}\n')
381 nativeFileClassCpp.write(' if ((ret != NULL && ' + knowTypes[t][3] + ') || (doc == NULL && ret != NULL && ret->isReference())) return ' + knowTypes[t][1] + ';\n')
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000382
edisonn@google.com571c70b2013-07-10 17:09:50 +0000383 if field.fRequired:
384 nativeFileClassCpp.write(' // TODO(edisonn): warn about missing required field, assert for known good pdfs\n')
385 nativeFileClassCpp.write(' return ' + knowTypes[t][2].toCpp() + ';\n');
386 elif prop.fDefault != '':
387 nativeFileClassCpp.write(' return ' + prop.fDefault.toCpp() + ';\n');
edisonn@google.com1277cf02013-06-17 23:36:45 +0000388 else:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000389 nativeFileClassCpp.write(' // TODO(edisonn): warn about missing default value for optional fields\n')
390 nativeFileClassCpp.write(' return ' + knowTypes[t][2].toCpp() + ';\n');
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000391
edisonn@google.com571c70b2013-07-10 17:09:50 +0000392 nativeFileClassCpp.write('}\n')
393 nativeFileClassCpp.write('\n')
edisonn@google.com1277cf02013-06-17 23:36:45 +0000394 else:
395 for type in prop.fTypes.split():
396 t = type.strip()
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000397
edisonn@google.com571c70b2013-07-10 17:09:50 +0000398 nativeFileClass.write(' bool is' + prop.fCppName + 'A' + t.title() + '(const SkNativeParsedPDF* doc);\n')
edisonn@google.com1277cf02013-06-17 23:36:45 +0000399
edisonn@google.com571c70b2013-07-10 17:09:50 +0000400 nativeFileClassCpp.write('bool SkPdf' + cls.fName + '::is' + prop.fCppName + 'A' + t.title() + '(const SkNativeParsedPDF* doc) {\n')
401 nativeFileClassCpp.write(' SkPdfObject* ret = get(\"' + prop.fName + '\", \"' + prop.fAbr + '\");\n')
402 nativeFileClassCpp.write(' if (doc) {ret = doc->resolveReference(ret);}\n')
403 nativeFileClassCpp.write(' return ret != NULL && ' + knowTypes[t][3] + ';\n')
404 nativeFileClassCpp.write('}\n')
405 nativeFileClassCpp.write('\n')
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000406
edisonn@google.com571c70b2013-07-10 17:09:50 +0000407 nativeFileClass.write(' ' + knowTypes[t][0] + ' get' + prop.fCppName + 'As' + t.title() + '(const SkNativeParsedPDF* doc);\n')
408 nativeFileClassCpp.write('' + knowTypes[t][0] + ' SkPdf' + cls.fName + '::get' + prop.fCppName + 'As' + t.title() + '(const SkNativeParsedPDF* doc) {\n')
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000409
edisonn@google.com571c70b2013-07-10 17:09:50 +0000410 nativeFileClassCpp.write(' SkPdfObject* ret = get(\"' + prop.fName + '\", \"' + prop.fAbr + '\");\n')
411 nativeFileClassCpp.write(' if (doc) {ret = doc->resolveReference(ret);}\n')
412 nativeFileClassCpp.write(' if ((ret != NULL && ' + knowTypes[t][3] + ') || (doc == NULL && ret != NULL && ret->isReference())) return ' + knowTypes[t][1] + ';\n')
413
414
415 if field.fRequired:
416 nativeFileClassCpp.write(' // TODO(edisonn): warn about missing required field, assert for known good pdfs\n')
417 nativeFileClassCpp.write(' return ' + knowTypes[t][2].toCpp() + ';\n');
418 elif prop.fDefault != '':
419 nativeFileClassCpp.write(' return ' + prop.fDefault.toCpp() + ';\n');
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000420 else:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000421 nativeFileClassCpp.write(' // TODO(edisonn): warn about missing default value for optional fields\n')
422 nativeFileClassCpp.write(' return ' + knowTypes[t][2].toCpp() + ';\n');
423
424 nativeFileClassCpp.write('}\n')
425 nativeFileClassCpp.write('\n')
edisonn@google.com1277cf02013-06-17 23:36:45 +0000426
edisonn@google.com571c70b2013-07-10 17:09:50 +0000427 nativeFileClass.write(' bool has_' + prop.fCppName + '() const;\n')
428 nativeFileClassCpp.write('bool SkPdf' + cls.fName + '::has_' + prop.fCppName + '() const {\n')
429 # TODO(edisonn): has_foo() does not check type, add has_valid_foo(), and check that type is expected (e.g. number, string, ...)
430 nativeFileClassCpp.write(' return get(\"' + prop.fName + '\", \"' + prop.fAbr + '\") != NULL;\n')
431 nativeFileClassCpp.write('}\n')
432 nativeFileClassCpp.write('\n')
edisonn@google.com45327112013-06-13 20:02:29 +0000433
edisonn@google.coma2fab9d2013-06-14 19:22:19 +0000434 if prop.fCppName[0] == '[':
edisonn@google.com571c70b2013-07-10 17:09:50 +0000435 nativeFileClass.write('*/\n') # comment code of the atributes that can have any name
436 nativeFileClassCpp.write('*/\n') # comment code of the atributes that can have any name
edisonn@google.com45327112013-06-13 20:02:29 +0000437
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000438
edisonn@google.com571c70b2013-07-10 17:09:50 +0000439 nativeFileClass.write('};\n')
440 nativeFileClass.write('\n')
edisonn@google.com59543d32013-06-18 22:00:40 +0000441
edisonn@google.com571c70b2013-07-10 17:09:50 +0000442 nativeFileClass.write('#endif // __DEFINED__NATIVE_SkPdf' + cls.fName + '\n')
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000443
edisonn@google.com571c70b2013-07-10 17:09:50 +0000444 nativeFileClass.close()
445 nativeFileClassCpp.close()
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000446
447 # generate constructor when knowing the type
448 # later, p2, generate constructor when not knowing the type - very similar with parsing?
449
edisonn@google.comf7dd4912013-06-11 23:06:16 +0000450 # generate parser
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000451 # TODO(edisonn): fast recognition based on must attributes.
edisonn@google.com571c70b2013-07-10 17:09:50 +0000452 fileMapperNative = open(sys.argv[1] + 'native/autogen/SkPdfMapper_autogen.h', 'w')
453 fileMapperNativeCpp = open(sys.argv[1] + 'native/autogen/SkPdfMapper_autogen.cpp', 'w')
edisonn@google.com59543d32013-06-18 22:00:40 +0000454
edisonn@google.com571c70b2013-07-10 17:09:50 +0000455 fileMapperNative.write('#ifndef __DEFINED__SkPdfMapper\n')
456 fileMapperNative.write('#define __DEFINED__SkPdfMapper\n')
457 fileMapperNative.write('\n')
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000458
edisonn@google.com571c70b2013-07-10 17:09:50 +0000459 fileMapperNative.write('#include "SkPdfHeaders_autogen.h"\n')
460 fileMapperNative.write('#include "SkNativeParsedPDF.h"\n')
461 fileMapperNative.write('#include "SkPdfObject.h"\n')
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000462
463
edisonn@google.com571c70b2013-07-10 17:09:50 +0000464 fileMapperNativeCpp.write('#include "SkPdfMapper_autogen.h"\n')
465 fileMapperNativeCpp.write('#include "SkPdfUtils.h"\n')
466 fileMapperNativeCpp.write('#include "SkPdfObject.h"\n')
467 fileMapperNativeCpp.write('\n')
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000468
edisonn@google.com571c70b2013-07-10 17:09:50 +0000469 fileMapperNative.write('class SkPdfMapper {\n')
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000470
edisonn@google.com571c70b2013-07-10 17:09:50 +0000471 fileMapperNative.write(' const SkNativeParsedPDF* fParsedDoc;\n')
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000472
edisonn@google.com571c70b2013-07-10 17:09:50 +0000473 fileMapperNative.write('public:\n')
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000474
edisonn@google.com571c70b2013-07-10 17:09:50 +0000475 fileMapperNative.write(' SkPdfMapper(const SkNativeParsedPDF* doc) : fParsedDoc(doc) {}\n')
476 fileMapperNative.write('\n')
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000477
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000478 for name in self.fClassesNamesInOrder:
479 cls = self.fClasses[name]
480
edisonn@google.com571c70b2013-07-10 17:09:50 +0000481 fileMapperNative.write(' SkPdfObjectType map' + name + '(const SkPdfObject* in) const;\n')
edisonn@google.com68d15c82013-06-17 20:46:27 +0000482
edisonn@google.com571c70b2013-07-10 17:09:50 +0000483 fileMapperNativeCpp.write('SkPdfObjectType SkPdfMapper::map' + name + '(const SkPdfObject* in) const {\n')
484 fileMapperNativeCpp.write(' if (!is' + name + '(in)) return kNone_SkPdfObjectType;\n')
485 fileMapperNativeCpp.write('\n')
486 if len(cls.fEnumSubclasses) > 0:
487 fileMapperNativeCpp.write(' SkPdfObjectType ret;\n')
edisonn@google.comff278442013-06-21 21:03:15 +0000488
489 # stream must be last one
490 hasStream = False
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000491 for sub in cls.fEnumSubclasses:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000492 fileMapperNativeCpp.write(' if (kNone_SkPdfObjectType != (ret = map' + enumToCls[sub].fName + '(in))) return ret;\n')
edisonn@google.comff278442013-06-21 21:03:15 +0000493
edisonn@google.com571c70b2013-07-10 17:09:50 +0000494 fileMapperNativeCpp.write('\n')
edisonn@google.comff278442013-06-21 21:03:15 +0000495
edisonn@google.com571c70b2013-07-10 17:09:50 +0000496 fileMapperNativeCpp.write(' return k' + name + '_SkPdfObjectType;\n')
497 fileMapperNativeCpp.write('}\n')
498 fileMapperNativeCpp.write('\n')
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000499
500 for name in self.fClassesNamesInOrder:
501 cls = self.fClasses[name]
502
edisonn@google.com571c70b2013-07-10 17:09:50 +0000503 fileMapperNative.write(' bool is' + name + '(const SkPdfObject* nativeObj) const ;\n')
504 fileMapperNativeCpp.write('bool SkPdfMapper::is' + name + '(const SkPdfObject* nativeObj) const {\n')
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000505
edisonn@google.coma2fab9d2013-06-14 19:22:19 +0000506 if cls.fCheck != '':
edisonn@google.com571c70b2013-07-10 17:09:50 +0000507 fileMapperNativeCpp.write(' return ' + cls.fCheck + ';\n')
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000508 else:
edisonn@google.coma2fab9d2013-06-14 19:22:19 +0000509 cntMust = 0
edisonn@google.com571c70b2013-07-10 17:09:50 +0000510 emitedRet = False
edisonn@google.coma2fab9d2013-06-14 19:22:19 +0000511 for field in cls.fFields:
512 prop = field.fProp
513 if prop.fHasMust:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000514 if emitedRet == False:
515 fileMapperNativeCpp.write(' const SkPdfObject* ret = NULL;\n')
516 emitedRet = True
edisonn@google.coma2fab9d2013-06-14 19:22:19 +0000517 cntMust = cntMust + 1
edisonn@google.com571c70b2013-07-10 17:09:50 +0000518 fileMapperNativeCpp.write(' if (!nativeObj->isDictionary()) return false;\n')
519 fileMapperNativeCpp.write(' ret = nativeObj->get(\"' + prop.fName + '\", \"' + prop.fAbr + '\");\n')
520 fileMapperNativeCpp.write(' if (ret == NULL) return false;\n')
edisonn@google.comff278442013-06-21 21:03:15 +0000521
522 eval = '';
523 # TODO(edisonn): this could get out of hand, and could have poor performance if continued on this path
524 # but if we would write our parser, then best thing would be to create a map of (key, value) -> to bits
525 # 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
526 # and for non unique posinilities (if any) based on context, or the requester of dictionry we can determine fast the dictionary type
527 mustBe = self.determineAllMustBe(cls, field, enumToCls)
528 if len(mustBe) > 0:
529 for cnd in mustBe:
530 if eval == '':
edisonn@google.com571c70b2013-07-10 17:09:50 +0000531 eval = '(' + knowTypes[prop.fTypes.strip()][1] + ' != ' + cnd.toCpp() + ')'
edisonn@google.comff278442013-06-21 21:03:15 +0000532 else:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000533 eval = eval + ' && ' + '(' + knowTypes[prop.fTypes.strip()][1] + ' != ' + cnd.toCpp() + ')'
534 fileMapperNativeCpp.write(' if (' + eval + ') return false;\n')
535 fileMapperNativeCpp.write('\n')
edisonn@google.coma2fab9d2013-06-14 19:22:19 +0000536
edisonn@google.com571c70b2013-07-10 17:09:50 +0000537 fileMapperNativeCpp.write(' return true;\n')
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000538
edisonn@google.com571c70b2013-07-10 17:09:50 +0000539 fileMapperNativeCpp.write('}\n')
540 fileMapperNativeCpp.write('\n')
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000541
edisonn@google.com571c70b2013-07-10 17:09:50 +0000542 # TODO(edisonn): dict should be a SkPdfDictionary ?
543 fileMapperNative.write(' bool SkPdf' + name + 'FromDictionary(const SkPdfObject* dict, const char* key, SkPdf' + name + '** data) const ;\n')
544 fileMapperNativeCpp.write('bool SkPdfMapper::SkPdf' + name + 'FromDictionary(const SkPdfObject* dict, const char* key, SkPdf' + name + '** data) const {\n')
545 fileMapperNativeCpp.write(' const SkPdfObject* value = dict->get(key);\n')
546 fileMapperNativeCpp.write(' if (value == NULL) { return false; }\n')
547 fileMapperNativeCpp.write(' if (data == NULL) { return true; }\n')
548 fileMapperNativeCpp.write(' if (kNone_SkPdfObjectType == map' + name + '(value)) return false;\n')
549 fileMapperNativeCpp.write(' *data = (SkPdf' + name + '*)value;\n')
550 fileMapperNativeCpp.write(' return true;\n');
551 fileMapperNativeCpp.write('}\n')
552 fileMapperNativeCpp.write('\n')
edisonn@google.com131d4ee2013-06-26 17:48:12 +0000553
edisonn@google.com571c70b2013-07-10 17:09:50 +0000554 fileMapperNative.write(' bool SkPdf' + name + 'FromDictionary(const SkPdfObject* dict, const char* key, const char* abr, SkPdf' + name + '** data) const ;\n')
555 fileMapperNativeCpp.write('bool SkPdfMapper::SkPdf' + name + 'FromDictionary(const SkPdfObject* dict, const char* key, const char* abr, SkPdf' + name + '** data) const {\n')
556 fileMapperNativeCpp.write(' if (SkPdf' + name + 'FromDictionary(dict, key, data)) return true;\n')
557 fileMapperNativeCpp.write(' if (abr == NULL || *abr == \'\\0\') return false;\n')
558 fileMapperNativeCpp.write(' return SkPdf' + name + 'FromDictionary(dict, abr, data);\n')
559 fileMapperNativeCpp.write('}\n')
560 fileMapperNativeCpp.write('\n')
edisonn@google.com131d4ee2013-06-26 17:48:12 +0000561
edisonn@google.com571c70b2013-07-10 17:09:50 +0000562 fileMapperNative.write('};\n')
563 fileMapperNative.write('\n')
edisonn@google.com59543d32013-06-18 22:00:40 +0000564
edisonn@google.com571c70b2013-07-10 17:09:50 +0000565 fileMapperNative.write('#endif // __DEFINED__SkPdfMapper\n')
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000566
edisonn@google.com571c70b2013-07-10 17:09:50 +0000567 fileMapperNative.close()
568 fileMapperNativeCpp.close()
edisonn@google.comaf3daa02013-06-12 19:07:45 +0000569
edisonn@google.com1a191c62013-06-11 21:44:08 +0000570 return
571
572def generateCode():
edisonn@google.com571c70b2013-07-10 17:09:50 +0000573 global fileHeadersNative
574 global fileHeadersNativeCpp
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000575 global knowTypes
edisonn@google.com59543d32013-06-18 22:00:40 +0000576
edisonn@google.com571c70b2013-07-10 17:09:50 +0000577 fileHeadersNative = open(sys.argv[1] + 'native/autogen/SkPdfHeaders_autogen.h', 'w')
578 fileHeadersNativeCpp = open(sys.argv[1] + 'native/autogen/SkPdfHeaders_autogen.cpp', 'w')
edisonn@google.com59543d32013-06-18 22:00:40 +0000579
edisonn@google.com571c70b2013-07-10 17:09:50 +0000580 fileHeadersNative.write('#ifndef __DEFINED__SkPdfHeaders\n')
581 fileHeadersNative.write('#define __DEFINED__SkPdfHeaders\n')
582 fileHeadersNative.write('\n')
edisonn@google.com59543d32013-06-18 22:00:40 +0000583
edisonn@google.com571c70b2013-07-10 17:09:50 +0000584 fileHeadersNativeCpp.write('#include "SkPdfHeaders_autogen.h"\n')
edisonn@google.com131d4ee2013-06-26 17:48:12 +0000585
edisonn@google.coma2fab9d2013-06-14 19:22:19 +0000586 manager = PdfClassManager()
edisonn@google.com1a191c62013-06-11 21:44:08 +0000587
edisonn@google.coma2fab9d2013-06-14 19:22:19 +0000588 # these classes are not explicitely backed by a table in the pdf spec
edisonn@google.com571c70b2013-07-10 17:09:50 +0000589 manager.addClass('Dictionary')
edisonn@google.coma2fab9d2013-06-14 19:22:19 +0000590 manager.addClass('XObjectDictionary', 'Dictionary')
591
592 manager.addClass('FontDictionary', 'Dictionary')
593
edisonn@google.comff278442013-06-21 21:03:15 +0000594 manager.addClass('TrueTypeFontDictionary', 'Type1FontDictionary')\
595 .required('NULL')\
596 .field('Subtype')\
597 .name('Subtype')\
598 .type('name')\
599 .comment('')\
600 .must([datatypes.PdfName('TrueType')])\
601 .done().done()\
edisonn@google.coma2fab9d2013-06-14 19:22:19 +0000602
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000603 addDictionaryTypesTo(knowTypes)
604 buildPdfSpec(manager)
edisonn@google.com1a191c62013-06-11 21:44:08 +0000605
edisonn@google.coma2fab9d2013-06-14 19:22:19 +0000606 manager.addClass('MultiMasterFontDictionary', 'Type1FontDictionary')\
607 .required('NULL')\
608 .field('Subtype')\
609 .name('Subtype')\
edisonn@google.com45327112013-06-13 20:02:29 +0000610 .type('name')\
edisonn@google.coma2fab9d2013-06-14 19:22:19 +0000611 .comment('')\
edisonn@google.comff278442013-06-21 21:03:15 +0000612 .must([datatypes.PdfName('MMType1')])\
edisonn@google.com45327112013-06-13 20:02:29 +0000613 .done().done()\
edisonn@google.com45327112013-06-13 20:02:29 +0000614
615
edisonn@google.coma2fab9d2013-06-14 19:22:19 +0000616 manager.write()
edisonn@google.com1a191c62013-06-11 21:44:08 +0000617
edisonn@google.com571c70b2013-07-10 17:09:50 +0000618 fileHeadersNative.write('#endif // __DEFINED__SkPdfHeaders\n')
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000619
edisonn@google.com571c70b2013-07-10 17:09:50 +0000620 fileHeadersNative.close()
621 fileHeadersNativeCpp.close()
edisonn@google.com1a191c62013-06-11 21:44:08 +0000622
623if '__main__' == __name__:
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000624 #print sys.argv
edisonn@google.com1a191c62013-06-11 21:44:08 +0000625 sys.exit(generateCode())
edisonn@google.com45327112013-06-13 20:02:29 +0000626