OLD | NEW |
1 import sys | 1 import sys |
2 | 2 |
3 class PdfName: | 3 class PdfName: |
4 def __init__(self, name, abr=''): | 4 def __init__(self, name, abr=''): |
5 self.fName = name | 5 self.fName = name |
6 self.fAbr = abr | 6 self.fAbr = abr |
| 7 |
| 8 def toCpp(self): |
| 9 return '\"' + self.fName + '\"' |
| 10 |
| 11 class PdfString: |
| 12 def __init__(self, value): |
| 13 self.fValue = value |
| 14 |
| 15 def toCpp(self): |
| 16 return '\"' + self.fValue + '\"' |
7 | 17 |
8 class PdfInteger: | 18 class PdfInteger: |
9 def __init__(self, value): | 19 def __init__(self, value): |
10 self.fValue = value | 20 self.fValue = value |
11 | 21 |
| 22 def toCpp(self): |
| 23 return str(self.fValue) |
| 24 |
12 class PdfReal: | 25 class PdfReal: |
13 def __init__(self, value): | 26 def __init__(self, value): |
14 self.fValue = value | 27 self.fValue = value |
15 | 28 |
| 29 def toCpp(self): |
| 30 return str(self.fValue) |
| 31 |
16 class PdfString: | 32 class PdfString: |
17 def __init__(self, value): | 33 def __init__(self, value): |
18 self.fValue = value | 34 self.fValue = value |
19 | 35 |
| 36 def toCpp(self): |
| 37 return self.fValue |
| 38 |
20 class PdfBoolean: | 39 class PdfBoolean: |
21 def __init__(self, value): | 40 def __init__(self, value): |
22 self.fValue = value | 41 self.fValue = value |
23 | 42 |
| 43 def toCpp(self): |
| 44 return self.fValue |
| 45 |
24 class PdfField: | 46 class PdfField: |
25 def __init__(self, parent, name, abr): | 47 def __init__(self, parent, name, abr): |
26 self.fParent = parent | 48 self.fParent = parent |
27 self.fName = name | 49 self.fName = name |
28 self.fAbr = abr | 50 self.fAbr = abr |
29 | 51 |
30 self.fDefault = '' | 52 self.fDefault = '' |
31 self.fType = '' | 53 self.fType = '' |
| 54 self.fCppName = '' |
| 55 self.fCppType = '' |
| 56 self.fCppReader = '' |
| 57 self.fValidOptions = [] |
| 58 self.fHasMust = False |
| 59 self.fMustBe = '' |
32 | 60 |
33 def must(self, value): | 61 def must(self, value): |
34 return self.fParent | 62 self.fHasMust = True |
| 63 self.fMustBe = value |
| 64 return self |
35 | 65 |
36 def default(self, value): | 66 def default(self, value): |
37 self.fDefault = value | 67 self.fDefault = value |
38 return self | 68 return self |
39 | 69 |
40 def number(self): | 70 def number(self, name): |
41 self.fType = 'number' | 71 self.fType = 'number' |
| 72 self.fCppName = name |
| 73 self.fCppType = 'double' |
| 74 self.fCppReader = 'DoubleFromDictionary' |
42 return self | 75 return self |
43 | 76 |
44 def integer(self): | 77 def integer(self, name): |
45 self.fType = 'integer' | 78 self.fType = 'integer' |
| 79 self.fCppName = name |
| 80 self.fCppType = 'long' |
| 81 self.fCppReader = 'LongFromDictionary' |
46 return self | 82 return self |
47 | 83 |
48 def real(self): | 84 def real(self, name): |
49 self.fType = 'real' | 85 self.fType = 'real' |
| 86 self.fCppName = name |
| 87 self.fCppType = 'double' |
| 88 self.fCppReader = 'DoubleFromDictionary' |
50 return self | 89 return self |
51 | 90 |
52 def name(self): | 91 def name(self, name): |
53 self.fType = 'name' | 92 self.fType = 'name' |
| 93 self.fCppName = name |
| 94 self.fCppType = 'std::string' |
| 95 self.fCppReader = 'NameFromDictionary' |
54 return self | 96 return self |
55 | 97 |
56 def string(self): | 98 def string(self, name): |
57 self.fType = 'string' | 99 self.fType = 'string' |
| 100 self.fCppName = name |
| 101 self.fCppType = 'std::string' |
| 102 self.fCppReader = 'StringFromDictionary' |
58 return self | 103 return self |
59 | 104 |
60 def multiple(self, options): | 105 def multiple(self, validOptions): |
61 self.fType = 'multiple' | 106 self.fValidOptions = validOptions |
62 self.fOptions = options | |
63 return self | 107 return self |
64 | 108 |
65 def done(self): | 109 def done(self): |
66 return self.fParent | 110 return self.fParent |
67 | 111 |
68 | 112 |
69 class PdfClassField: | 113 class PdfClassField: |
70 def __init__(self, parent, required): | 114 def __init__(self, parent, required): |
71 self.fFields = [] | 115 #self.fProp = '' |
72 self.fIncludes = [] | |
73 self.fCC = [] | |
74 self.fParent = parent | 116 self.fParent = parent |
75 self.fRequired = required | 117 self.fRequired = required |
76 | 118 |
77 def hasField(self, name, abr=''): | 119 def field(self, name, abr=''): |
78 return PdfField(self, name, abr) | 120 self.fProp = PdfField(self, name, abr) |
| 121 return self.fProp |
79 | 122 |
80 def done(self): | 123 def done(self): |
81 return self.fParent | 124 return self.fParent |
82 | 125 |
83 class PdfClass: | 126 class PdfClass: |
84 def __init__(self, name, base): | 127 def __init__(self, name, base): |
85 self.fFields = [] | 128 self.fFields = [] |
86 self.fIncludes = [] | 129 self.fIncludes = [] |
87 self.fCC = [] | 130 self.fCCPublic = [] |
| 131 self.fCCPrivate = [] |
88 self.fName = name | 132 self.fName = name |
89 self.fBase = base | 133 self.fBase = base |
90 | 134 |
91 self.fEnumSubclasses = [] | 135 self.fEnumSubclasses = [] |
92 | 136 |
93 self.fEnum = '!UNDEFINED' | 137 self.fEnum = '!UNDEFINED' |
94 self.fEnumEnd = '!UNDEFINED' | 138 self.fEnumEnd = '!UNDEFINED' |
95 | 139 |
96 def required(self): | 140 def required(self, badDefault): |
97 field = PdfClassField(self, True) | 141 field = PdfClassField(self, True) |
| 142 field.fBadDefault = badDefault |
98 self.fFields.append(field) | 143 self.fFields.append(field) |
99 return field | 144 return field |
100 | 145 |
101 def optional(self): | 146 def optional(self): |
102 field = PdfClassField(self, False) | 147 field = PdfClassField(self, False) |
103 self.fFields.append(field) | 148 self.fFields.append(field) |
104 return field | 149 return field |
105 | 150 |
106 def include(self, path): | 151 def include(self, path): |
107 self.fIncludes.append(path) | 152 self.fIncludes.append(path) |
108 return self | 153 return self |
109 | 154 |
110 def carbonCopy(self, cc): | 155 def carbonCopyPublic(self, cc): |
111 self.fCC.append(cc) | 156 self.fCCPublic.append(cc) |
| 157 return self |
| 158 |
| 159 def carbonCopyPrivate(self, cc): |
| 160 self.fCCPrivate.append(cc) |
112 return self | 161 return self |
113 | 162 |
114 class PdfClassManager: | 163 class PdfClassManager: |
115 def __init__(self): | 164 def __init__(self): |
116 self.fClasses = {} | 165 self.fClasses = {} |
| 166 self.fClassesNamesInOrder = [] |
117 | 167 |
118 def addClass(self, name, base=''): | 168 def addClass(self, name, base='Object'): |
119 cls = PdfClass(name, base) | 169 if name == 'Object': |
| 170 cls = PdfClass(name, '') |
| 171 else: |
| 172 cls = PdfClass(name, base) |
120 self.fClasses[name] = cls | 173 self.fClasses[name] = cls |
| 174 self.fClassesNamesInOrder.append(name) |
121 return cls | 175 return cls |
122 | 176 |
123 def longName(self, name): | 177 def longName(self, name): |
124 ret = '' | 178 ret = '' |
125 while name != '': | 179 while name != '': |
126 cls = self.fClasses[name] | 180 cls = self.fClasses[name] |
127 ret = name + ret | 181 ret = name + ret |
128 name = cls.fBase | 182 name = cls.fBase |
129 | 183 |
130 return ret | 184 return ret |
131 | 185 |
132 | 186 |
133 def writeEnum(self, enum, enumToCls): | 187 def writeEnum(self, enum, enumToCls): |
134 print(' ' + enum + ',') | 188 print(' ' + enum + ',') |
135 cls = enumToCls[enum] | 189 cls = enumToCls[enum] |
136 cls.fEnumSubclasses.sort() | 190 cls.fEnumSubclasses.sort() |
137 | 191 |
138 cnt = 0 | 192 cnt = 0 |
139 for sub in cls.fEnumSubclasses: | 193 for sub in cls.fEnumSubclasses: |
140 self.writeEnum(cls.fEnumSubclasses[cnt], enumToCls) | 194 self.writeEnum(cls.fEnumSubclasses[cnt], enumToCls) |
141 cnt = cnt + 1 | 195 cnt = cnt + 1 |
142 | 196 |
143 if cnt != 0: | 197 if cnt != 0: |
144 print(' ' + cls.fEnumEnd + ',') | 198 print(' ' + cls.fEnumEnd + ',') |
| 199 |
| 200 |
| 201 def writeAsNull(self, cls, enumToCls): |
| 202 print(' virtual SkPdf' + cls.fName +'* as' + cls.fName + '() {return NULL;}
') |
| 203 print(' virtual const SkPdf' + cls.fName +'* as' + cls.fName + '() const {r
eturn NULL;}') |
| 204 print |
| 205 |
| 206 cnt = 0 |
| 207 for sub in cls.fEnumSubclasses: |
| 208 self.writeAsNull(enumToCls[cls.fEnumSubclasses[cnt]], enumToCls) |
| 209 cnt = cnt + 1 |
| 210 |
| 211 |
| 212 def writeAsFoo(self, cls, enumToCls): |
| 213 # TODO(edisonn): add a container, with sections, public, private, default, .
.. |
| 214 # the end code will be grouped |
| 215 |
| 216 # me |
| 217 print('public:') |
| 218 print(' virtual SkPdf' + cls.fName +'* as' + cls.fName + '() {return this;}
') |
| 219 print(' virtual const SkPdf' + cls.fName +'* as' + cls.fName + '() const {r
eturn this;}') |
| 220 print |
| 221 |
| 222 if cls.fName == 'Object': |
| 223 cnt = 0 |
| 224 for sub in cls.fEnumSubclasses: |
| 225 self.writeAsNull(enumToCls[cls.fEnumSubclasses[cnt]], enumToCls) |
| 226 cnt = cnt + 1 |
| 227 |
| 228 if cls.fName != 'Object': |
| 229 print('private:') |
| 230 base = self.fClasses[cls.fBase] |
| 231 cnt = 0 |
| 232 for sub in base.fEnumSubclasses: |
| 233 if enumToCls[base.fEnumSubclasses[cnt]].fName != cls.fName: |
| 234 self.writeAsNull(enumToCls[base.fEnumSubclasses[cnt]], enumToCls) |
| 235 cnt = cnt + 1 |
| 236 |
| 237 |
145 | 238 |
146 def write(self): | 239 def write(self): |
147 # generate enum | 240 # generate enum |
148 enumsRoot = [] | 241 enumsRoot = [] |
149 | 242 |
150 enumToCls = {} | 243 enumToCls = {} |
151 | 244 |
152 for name in self.fClasses: | 245 for name in self.fClasses: |
153 cls = self.fClasses[name] | 246 cls = self.fClasses[name] |
154 enum = self.longName(name) | 247 enum = self.longName(name) |
155 cls.fEnum = 'k' + enum + '_PdfObjectType' | 248 cls.fEnum = 'k' + enum + '_SkPdfObjectType' |
156 cls.fEnumEnd = 'k' + enum + '__End_PdfObjectType' | 249 cls.fEnumEnd = 'k' + enum + '__End_SkPdfObjectType' |
157 | 250 |
158 if cls.fBase != '': | 251 if cls.fBase != '': |
159 self.fClasses[cls.fBase].fEnumSubclasses.append(cls.fEnum) | 252 self.fClasses[cls.fBase].fEnumSubclasses.append(cls.fEnum) |
160 | 253 |
161 if cls.fBase == '': | 254 if cls.fBase == '': |
162 enumsRoot.append(cls.fEnum) | 255 enumsRoot.append(cls.fEnum) |
163 | 256 |
164 enumToCls[cls.fEnum] = cls | 257 enumToCls[cls.fEnum] = cls |
165 | 258 |
166 enumsRoot.sort() | 259 enumsRoot.sort() |
167 | 260 |
| 261 |
| 262 # TODO(edisonn): move each .h in it's own file |
| 263 # write imports |
| 264 |
168 # write enums | 265 # write enums |
169 print('enum PdfObjectType {') | 266 print('enum SkPdfObjectType {') |
170 for enum in enumsRoot: | 267 for enum in enumsRoot: |
171 self.writeEnum(enum, enumToCls) | 268 self.writeEnum(enum, enumToCls) |
172 print('};') | 269 print('};') |
| 270 print |
| 271 |
| 272 # write forward class declaration |
| 273 for name in self.fClassesNamesInOrder: |
| 274 print('class SkPdf' + name + ';') |
| 275 print |
| 276 |
| 277 for name in self.fClassesNamesInOrder: |
| 278 cls = self.fClasses[name] |
| 279 enum = cls.fEnum |
173 | 280 |
174 # generate each class | 281 if cls.fBase == '': |
| 282 print('class SkPdf' + cls.fName + ' {') |
| 283 else: |
| 284 print('class SkPdf' + cls.fName + ' : public SkPdf' + cls.fBase + ' {') |
| 285 |
| 286 print('public:') |
| 287 print(' virtual SkPdfObjectType getType() const { return ' + cls.fEnum +
';}') |
| 288 if len(cls.fEnumSubclasses) == 0: |
| 289 print(' virtual SkPdfObjectType getTypeEnd() const { return (SkPdfObjec
tType)(' + cls.fEnum + ' + 1);}') |
| 290 else: |
| 291 print(' virtual SkPdfObjectType getTypeEnd() const { return ' + cls.fEn
umEnd + ';}') |
| 292 |
| 293 |
| 294 self.writeAsFoo(cls, enumToCls) |
| 295 |
| 296 print('public:') |
| 297 for cc in cls.fCCPublic: |
| 298 print(' ' + cc) |
| 299 |
| 300 print('private:') |
| 301 for cc in cls.fCCPrivate: |
| 302 print(' ' + cc) |
| 303 |
| 304 if cls.fBase == '': |
| 305 print('protected:') |
| 306 print(' const PdfMemDocument* fPodofoDoc;') |
| 307 print(' const PdfObject* fPodofoObj;') |
| 308 print |
| 309 print('public:') |
| 310 print(' SkPdf' + cls.fName + '(const PdfMemDocument* podofoDoc, const P
dfObject* podofoObj) : fPodofoDoc(podofoDoc), fPodofoObj(podofoObj) {}') |
| 311 print(' const PdfObject* podofo() const { return fPodofoObj;}') |
| 312 else: |
| 313 print('public:') |
| 314 print(' SkPdf' + cls.fName + '(const PdfMemDocument* podofoDoc, const Pd
fObject* podofoObj) : SkPdf' + cls.fBase + '(podofoDoc, podofoObj) {}') |
| 315 |
| 316 #check required fieds, also, there should be an internal_valid() manually
wrote for complex |
| 317 # situations |
| 318 # right now valid return true |
| 319 print(' virtual bool valid() const {return true;}') |
| 320 |
| 321 for field in cls.fFields: |
| 322 prop = field.fProp |
| 323 if prop.fCppName != '': |
| 324 print(' ' + prop.fCppType + ' ' + prop.fCppName + '() const {') |
| 325 print(' ' + prop.fCppType + ' ret;') |
| 326 print(' if (' + prop.fCppReader + '(fPodofoDoc, fPodofoObj->GetDi
ctionary(), \"' + prop.fName + '\", \"' + prop.fAbr + '\", &ret)) return ret;') |
| 327 if field.fRequired == False: |
| 328 print(' return ' + prop.fDefault.toCpp() + ';'); |
| 329 if field.fRequired == True: |
| 330 print(' // TODO(edisonn): warn about missing required field, as
sert for known good pdfs') |
| 331 print(' return ' + field.fBadDefault + ';'); |
| 332 print(' }') |
| 333 print |
| 334 |
| 335 print('};') |
| 336 print |
| 337 print |
| 338 |
| 339 |
| 340 |
| 341 # generate constructor when knowing the type |
| 342 # later, p2, generate constructor when not knowing the type - very similar
with parsing? |
| 343 |
175 # generate parser | 344 # generate parser |
| 345 |
| 346 # TODO(edisonn): fast recognition based on must attributes. |
| 347 print('class PodofoMapper {') |
| 348 print('public:') |
| 349 for name in self.fClassesNamesInOrder: |
| 350 cls = self.fClasses[name] |
| 351 |
| 352 print(' static bool map' + name + '(const PdfMemDocument& podofoDoc, cons
t PdfObject& podofoObj, SkPdfObject** out) {') |
| 353 print(' if (!isA' + name + '(podofoDoc, podofoObj)) return false;') |
| 354 print |
| 355 |
| 356 for sub in cls.fEnumSubclasses: |
| 357 print(' if (map' + enumToCls[sub].fName + '(podofoDoc, podofoObj, out
)) return true;') |
| 358 |
| 359 print |
| 360 |
| 361 print(' *out = new SkPdf' + name + '(&podofoDoc, &podofoObj);') |
| 362 print(' return true;') |
| 363 print(' }') |
| 364 print |
| 365 |
| 366 for name in self.fClassesNamesInOrder: |
| 367 cls = self.fClasses[name] |
| 368 |
| 369 print(' static bool isA' + name + '(const PdfMemDocument& podofoDoc, cons
t PdfObject& podofoObj) {') |
| 370 |
| 371 cntMust = 0 |
| 372 for field in cls.fFields: |
| 373 prop = field.fProp |
| 374 if prop.fHasMust: |
| 375 cntMust = cntMust + 1 |
| 376 print(' ' + prop.fCppType + ' ' + prop.fCppName + ';') |
| 377 print(' if (!' + prop.fCppReader + '(&podofoDoc, podofoObj.GetDicti
onary(), \"' + prop.fName + '\", \"' + prop.fAbr + '\", &' + prop.fCppName + '))
return false;') |
| 378 print(' if (' + prop.fCppName + ' != ' + prop.fMustBe.toCpp() + ')
return false;') |
| 379 print |
| 380 |
| 381 # hack, we only care about dictionaries now, so ret tru only if there is a
match |
| 382 if cntMust != 0 or name == 'Object' or name == 'Dictionary': |
| 383 print(' return true;') |
| 384 else: |
| 385 print(' return false;') |
| 386 |
| 387 print(' }') |
| 388 print |
| 389 |
| 390 print('};') |
| 391 print |
| 392 |
176 return | 393 return |
177 | 394 |
178 def generateCode(): | 395 def generateCode(): |
179 all = PdfClassManager() | 396 all = PdfClassManager() |
180 | 397 |
181 all.addClass('Object') | 398 all.addClass('Object') |
182 all.addClass('Null') | 399 all.addClass('Null') |
183 all.addClass('Boolean') | 400 all.addClass('Boolean') |
184 all.addClass('Integer') | 401 all.addClass('Integer') |
185 all.addClass('Real') | 402 all.addClass('Real') |
186 all.addClass('Name') | 403 all.addClass('Name') |
187 all.addClass('Stream') | 404 all.addClass('Stream') |
188 all.addClass('Reference') | 405 all.addClass('Reference') |
189 all.addClass('Array') | 406 all.addClass('Array') |
190 all.addClass('Dictionary') | 407 all.addClass('Dictionary') |
191 | 408 |
192 all.addClass('XObject', 'Dictionary').required().hasField('/Type').must('/XObj
ect') | 409 all.addClass('XObject', 'Dictionary').required('""').field('Type').must(PdfNam
e('XObject')).name('t') |
193 | 410 |
194 all.addClass('Image', 'XObject').required().hasField('/Type').must('/XObject')
.done()\ | 411 all.addClass('Image', 'XObject').required('""').field('Type').must(PdfName('XO
bject')).name('t').done()\ |
195 .required().hasField('/Subtype').must('/Image'
).done()\ | 412 .done()\ |
196 .required().hasField('/Width', '/W').integer()
.done().done()\ | 413 .required('""').field('Subtype').must(PdfName(
'Image')).name('s').done()\ |
197 .required().hasField('/Height', '/H').integer(
).done().done()\ | 414 .done()\ |
198 .required().hasField('/ColorSpace').multiple([
PdfName('/DeviceRGB', '/RGB'), PdfName('/DeviceGray', '/Gray')])\ | 415 .required('-1').field('Width', 'W').integer('w
').done()\ |
| 416 .done()\ |
| 417 .required('-1').field('Height', 'H').integer('
h').done()\ |
| 418 .done()\ |
| 419 .required('""').field('ColorSpace').name('cs')
.multiple([PdfName('/DeviceRGB', '/RGB'), PdfName('/DeviceGray', '/Gray')]).done
()\ |
| 420 .done()\ |
| 421 .optional().field('BitsPerComponent', 'BPC').i
nteger('bpc').multiple([PdfInteger(1), PdfInteger(2), PdfInteger(4), PdfInteger(
8)])\ |
| 422
.default(PdfInteger(1)).done()\ |
199
.done()\ | 423
.done()\ |
200 .done()\ | 424 .carbonCopyPrivate('SkBitmap bitmap;') |
201 .optional().hasField('/BitsPerComponent', '/BP
C').multiple([PdfInteger(1), PdfInteger(2), PdfInteger(4), PdfInteger(8)])\ | |
202
.default(PdfInteger(1))\ | |
203
.done().done()\ | |
204 .carbonCopy('SkBitmap bitmap;') | |
205 | 425 |
206 all.addClass('Form', 'XObject').required().hasField('/Type').must('/XObject').
done()\ | 426 all.addClass('Form', 'XObject').required('""').field('Type').must(PdfName('XOb
ject')).name('t').done()\ |
207 .required().hasField('/Subtype').must('/Form').
done() | 427 .done()\ |
| 428 .required('""').field('Subtype').must(PdfName('
Form')).name('s').done()\ |
| 429 .done()\ |
| 430 .carbonCopyPublic('void test() {}') |
208 | 431 |
209 | 432 |
210 all.write() | 433 all.write() |
211 | 434 |
212 return 1 | 435 return 1 |
213 | 436 |
214 if '__main__' == __name__: | 437 if '__main__' == __name__: |
215 sys.exit(generateCode()) | 438 sys.exit(generateCode()) |
OLD | NEW |