]> git.saurik.com Git - android/aapt.git/blame - AaptAssets.h
Merge "Merge "AAPT: support a new --ignore-assets flag."" into jb-dev
[android/aapt.git] / AaptAssets.h
CommitLineData
a534180c
TAOSP
1//
2// Copyright 2006 The Android Open Source Project
3//
4// Information about assets being operated on.
5//
6#ifndef __AAPT_ASSETS_H
7#define __AAPT_ASSETS_H
8
9#include <stdlib.h>
34ceac87
MA
10#include <androidfw/AssetManager.h>
11#include <androidfw/ResourceTypes.h>
a534180c 12#include <utils/KeyedVector.h>
34ceac87 13#include <utils/RefBase.h>
a534180c
TAOSP
14#include <utils/SortedVector.h>
15#include <utils/String8.h>
34ceac87 16#include <utils/String8.h>
a534180c 17#include <utils/Vector.h>
1f170917 18#include "ZipFile.h"
a534180c
TAOSP
19
20#include "Bundle.h"
21#include "SourcePos.h"
22
23using namespace android;
24
d3535722
RM
25
26extern const char * const gDefaultIgnoreAssets;
27extern const char * gUserIgnoreAssets;
28
a534180c
TAOSP
29bool valid_symbol_name(const String8& str);
30
e29f4ada
DH
31class AaptAssets;
32
a534180c
TAOSP
33enum {
34 AXIS_NONE = 0,
35 AXIS_MCC = 1,
36 AXIS_MNC,
37 AXIS_LANGUAGE,
38 AXIS_REGION,
784c6915
DH
39 AXIS_SCREENLAYOUTSIZE,
40 AXIS_SCREENLAYOUTLONG,
a534180c 41 AXIS_ORIENTATION,
2ca01a37
TH
42 AXIS_UIMODETYPE,
43 AXIS_UIMODENIGHT,
a534180c
TAOSP
44 AXIS_DENSITY,
45 AXIS_TOUCHSCREEN,
46 AXIS_KEYSHIDDEN,
47 AXIS_KEYBOARD,
0096feb5 48 AXIS_NAVHIDDEN,
a534180c
TAOSP
49 AXIS_NAVIGATION,
50 AXIS_SCREENSIZE,
f1f3915b 51 AXIS_SMALLESTSCREENWIDTHDP,
4ee37df2
DH
52 AXIS_SCREENWIDTHDP,
53 AXIS_SCREENHEIGHTDP,
e29f4ada
DH
54 AXIS_VERSION,
55
56 AXIS_START = AXIS_MCC,
57 AXIS_END = AXIS_VERSION,
a534180c
TAOSP
58};
59
60/**
61 * This structure contains a specific variation of a single file out
62 * of all the variations it can have that we can have.
63 */
64struct AaptGroupEntry
65{
66public:
e29f4ada 67 AaptGroupEntry() : mParamsChanged(true) { }
a534180c 68 AaptGroupEntry(const String8& _locale, const String8& _vendor)
e29f4ada 69 : locale(_locale), vendor(_vendor), mParamsChanged(true) { }
a534180c
TAOSP
70
71 bool initFromDirName(const char* dir, String8* resType);
72
73 static status_t parseNamePart(const String8& part, int* axis, uint32_t* value);
e29f4ada
DH
74
75 static uint32_t getConfigValueForAxis(const ResTable_config& config, int axis);
76
77 static bool configSameExcept(const ResTable_config& config,
78 const ResTable_config& otherConfig, int axis);
79
a534180c
TAOSP
80 static bool getMccName(const char* name, ResTable_config* out = NULL);
81 static bool getMncName(const char* name, ResTable_config* out = NULL);
82 static bool getLocaleName(const char* name, ResTable_config* out = NULL);
784c6915
DH
83 static bool getScreenLayoutSizeName(const char* name, ResTable_config* out = NULL);
84 static bool getScreenLayoutLongName(const char* name, ResTable_config* out = NULL);
a534180c 85 static bool getOrientationName(const char* name, ResTable_config* out = NULL);
2ca01a37
TH
86 static bool getUiModeTypeName(const char* name, ResTable_config* out = NULL);
87 static bool getUiModeNightName(const char* name, ResTable_config* out = NULL);
a534180c
TAOSP
88 static bool getDensityName(const char* name, ResTable_config* out = NULL);
89 static bool getTouchscreenName(const char* name, ResTable_config* out = NULL);
90 static bool getKeysHiddenName(const char* name, ResTable_config* out = NULL);
91 static bool getKeyboardName(const char* name, ResTable_config* out = NULL);
92 static bool getNavigationName(const char* name, ResTable_config* out = NULL);
0096feb5 93 static bool getNavHiddenName(const char* name, ResTable_config* out = NULL);
a534180c 94 static bool getScreenSizeName(const char* name, ResTable_config* out = NULL);
f1f3915b 95 static bool getSmallestScreenWidthDpName(const char* name, ResTable_config* out = NULL);
4ee37df2
DH
96 static bool getScreenWidthDpName(const char* name, ResTable_config* out = NULL);
97 static bool getScreenHeightDpName(const char* name, ResTable_config* out = NULL);
a534180c
TAOSP
98 static bool getVersionName(const char* name, ResTable_config* out = NULL);
99
100 int compare(const AaptGroupEntry& o) const;
101
e29f4ada 102 const ResTable_config& toParams() const;
a534180c
TAOSP
103
104 inline bool operator<(const AaptGroupEntry& o) const { return compare(o) < 0; }
105 inline bool operator<=(const AaptGroupEntry& o) const { return compare(o) <= 0; }
106 inline bool operator==(const AaptGroupEntry& o) const { return compare(o) == 0; }
107 inline bool operator!=(const AaptGroupEntry& o) const { return compare(o) != 0; }
108 inline bool operator>=(const AaptGroupEntry& o) const { return compare(o) >= 0; }
109 inline bool operator>(const AaptGroupEntry& o) const { return compare(o) > 0; }
110
111 String8 toString() const;
112 String8 toDirName(const String8& resType) const;
e29f4ada
DH
113
114 const String8& getVersionString() const { return version; }
115
116private:
117 String8 mcc;
118 String8 mnc;
119 String8 locale;
120 String8 vendor;
121 String8 smallestScreenWidthDp;
122 String8 screenWidthDp;
123 String8 screenHeightDp;
124 String8 screenLayoutSize;
125 String8 screenLayoutLong;
126 String8 orientation;
127 String8 uiModeType;
128 String8 uiModeNight;
129 String8 density;
130 String8 touchscreen;
131 String8 keysHidden;
132 String8 keyboard;
133 String8 navHidden;
134 String8 navigation;
135 String8 screenSize;
136 String8 version;
137
138 mutable bool mParamsChanged;
139 mutable ResTable_config mParams;
a534180c
TAOSP
140};
141
142inline int compare_type(const AaptGroupEntry& lhs, const AaptGroupEntry& rhs)
143{
144 return lhs.compare(rhs);
145}
146
147inline int strictly_order_type(const AaptGroupEntry& lhs, const AaptGroupEntry& rhs)
148{
149 return compare_type(lhs, rhs) < 0;
150}
151
152class AaptGroup;
52ffc169 153class FilePathStore;
a534180c
TAOSP
154
155/**
156 * A single asset file we know about.
157 */
158class AaptFile : public RefBase
159{
160public:
161 AaptFile(const String8& sourceFile, const AaptGroupEntry& groupEntry,
162 const String8& resType)
163 : mGroupEntry(groupEntry)
164 , mResourceType(resType)
165 , mSourceFile(sourceFile)
166 , mData(NULL)
167 , mDataSize(0)
168 , mBufferSize(0)
169 , mCompression(ZipEntry::kCompressStored)
170 {
171 //printf("new AaptFile created %s\n", (const char*)sourceFile);
172 }
981d1579
MN
173 virtual ~AaptFile() {
174 free(mData);
175 }
a534180c
TAOSP
176
177 const String8& getPath() const { return mPath; }
178 const AaptGroupEntry& getGroupEntry() const { return mGroupEntry; }
179
180 // Data API. If there is data attached to the file,
181 // getSourceFile() is not used.
182 bool hasData() const { return mData != NULL; }
183 const void* getData() const { return mData; }
184 size_t getSize() const { return mDataSize; }
185 void* editData(size_t size);
186 void* editData(size_t* outSize = NULL);
187 void* padData(size_t wordSize);
188 status_t writeData(const void* data, size_t size);
189 void clearData();
190
191 const String8& getResourceType() const { return mResourceType; }
192
193 // File API. If the file does not hold raw data, this is
194 // a full path to a file on the filesystem that holds its data.
195 const String8& getSourceFile() const { return mSourceFile; }
196
197 String8 getPrintableSource() const;
198
199 // Desired compression method, as per utils/ZipEntry.h. For example,
200 // no compression is ZipEntry::kCompressStored.
201 int getCompressionMethod() const { return mCompression; }
202 void setCompressionMethod(int c) { mCompression = c; }
203private:
204 friend class AaptGroup;
205
206 String8 mPath;
207 AaptGroupEntry mGroupEntry;
208 String8 mResourceType;
209 String8 mSourceFile;
210 void* mData;
211 size_t mDataSize;
212 size_t mBufferSize;
213 int mCompression;
214};
215
216/**
217 * A group of related files (the same file, with different
218 * vendor/locale variations).
219 */
220class AaptGroup : public RefBase
221{
222public:
223 AaptGroup(const String8& leaf, const String8& path)
224 : mLeaf(leaf), mPath(path) { }
225 virtual ~AaptGroup() { }
226
227 const String8& getLeaf() const { return mLeaf; }
228
229 // Returns the relative path after the AaptGroupEntry dirs.
230 const String8& getPath() const { return mPath; }
231
232 const DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> >& getFiles() const
233 { return mFiles; }
234
235 status_t addFile(const sp<AaptFile>& file);
236 void removeFile(size_t index);
237
e29f4ada 238 void print(const String8& prefix) const;
a534180c
TAOSP
239
240 String8 getPrintableSource() const;
241
242private:
243 String8 mLeaf;
244 String8 mPath;
245
246 DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> > mFiles;
247};
248
249/**
e29f4ada 250 * A single directory of assets, which can contain files and other
a534180c
TAOSP
251 * sub-directories.
252 */
253class AaptDir : public RefBase
254{
255public:
256 AaptDir(const String8& leaf, const String8& path)
257 : mLeaf(leaf), mPath(path) { }
258 virtual ~AaptDir() { }
259
260 const String8& getLeaf() const { return mLeaf; }
261
262 const String8& getPath() const { return mPath; }
263
264 const DefaultKeyedVector<String8, sp<AaptGroup> >& getFiles() const { return mFiles; }
265 const DefaultKeyedVector<String8, sp<AaptDir> >& getDirs() const { return mDirs; }
266
e29f4ada 267 virtual status_t addFile(const String8& name, const sp<AaptGroup>& file);
a534180c
TAOSP
268
269 void removeFile(const String8& name);
270 void removeDir(const String8& name);
271
a534180c
TAOSP
272 /*
273 * Perform some sanity checks on the names of files and directories here.
274 * In particular:
275 * - Check for illegal chars in filenames.
276 * - Check filename length.
277 * - Check for presence of ".gz" and non-".gz" copies of same file.
278 * - Check for multiple files whose names match in a case-insensitive
279 * fashion (problematic for some systems).
280 *
281 * Comparing names against all other names is O(n^2). We could speed
282 * it up some by sorting the entries and being smarter about what we
283 * compare against, but I'm not expecting to have enough files in a
284 * single directory to make a noticeable difference in speed.
285 *
286 * Note that sorting here is not enough to guarantee that the package
287 * contents are sorted -- subsequent updates can rearrange things.
288 */
289 status_t validate() const;
290
e29f4ada 291 void print(const String8& prefix) const;
a534180c
TAOSP
292
293 String8 getPrintableSource() const;
294
295private:
e29f4ada
DH
296 friend class AaptAssets;
297
298 status_t addDir(const String8& name, const sp<AaptDir>& dir);
299 sp<AaptDir> makeDir(const String8& name);
300 status_t addLeafFile(const String8& leafName,
301 const sp<AaptFile>& file);
302 virtual ssize_t slurpFullTree(Bundle* bundle,
303 const String8& srcDir,
304 const AaptGroupEntry& kind,
305 const String8& resType,
306 sp<FilePathStore>& fullResPaths);
307
a534180c
TAOSP
308 String8 mLeaf;
309 String8 mPath;
310
311 DefaultKeyedVector<String8, sp<AaptGroup> > mFiles;
312 DefaultKeyedVector<String8, sp<AaptDir> > mDirs;
313};
314
315/**
316 * All information we know about a particular symbol.
317 */
318class AaptSymbolEntry
319{
320public:
321 AaptSymbolEntry()
6415576e 322 : isPublic(false), isJavaSymbol(false), typeCode(TYPE_UNKNOWN)
a534180c
TAOSP
323 {
324 }
325 AaptSymbolEntry(const String8& _name)
6415576e 326 : name(_name), isPublic(false), isJavaSymbol(false), typeCode(TYPE_UNKNOWN)
a534180c
TAOSP
327 {
328 }
329 AaptSymbolEntry(const AaptSymbolEntry& o)
330 : name(o.name), sourcePos(o.sourcePos), isPublic(o.isPublic)
6415576e 331 , isJavaSymbol(o.isJavaSymbol), comment(o.comment), typeComment(o.typeComment)
a534180c
TAOSP
332 , typeCode(o.typeCode), int32Val(o.int32Val), stringVal(o.stringVal)
333 {
334 }
335 AaptSymbolEntry operator=(const AaptSymbolEntry& o)
336 {
337 sourcePos = o.sourcePos;
338 isPublic = o.isPublic;
6415576e 339 isJavaSymbol = o.isJavaSymbol;
a534180c
TAOSP
340 comment = o.comment;
341 typeComment = o.typeComment;
342 typeCode = o.typeCode;
343 int32Val = o.int32Val;
344 stringVal = o.stringVal;
345 return *this;
346 }
347
348 const String8 name;
349
350 SourcePos sourcePos;
351 bool isPublic;
6415576e 352 bool isJavaSymbol;
a534180c
TAOSP
353
354 String16 comment;
355 String16 typeComment;
356
357 enum {
358 TYPE_UNKNOWN = 0,
359 TYPE_INT32,
360 TYPE_STRING
361 };
362
363 int typeCode;
364
365 // Value. May be one of these.
366 int32_t int32Val;
367 String8 stringVal;
368};
369
370/**
371 * A group of related symbols (such as indices into a string block)
372 * that have been generated from the assets.
373 */
374class AaptSymbols : public RefBase
375{
376public:
377 AaptSymbols() { }
378 virtual ~AaptSymbols() { }
379
380 status_t addSymbol(const String8& name, int32_t value, const SourcePos& pos) {
381 if (!check_valid_symbol_name(name, pos, "symbol")) {
382 return BAD_VALUE;
383 }
384 AaptSymbolEntry& sym = edit_symbol(name, &pos);
385 sym.typeCode = AaptSymbolEntry::TYPE_INT32;
386 sym.int32Val = value;
387 return NO_ERROR;
388 }
389
390 status_t addStringSymbol(const String8& name, const String8& value,
391 const SourcePos& pos) {
392 if (!check_valid_symbol_name(name, pos, "symbol")) {
393 return BAD_VALUE;
394 }
395 AaptSymbolEntry& sym = edit_symbol(name, &pos);
396 sym.typeCode = AaptSymbolEntry::TYPE_STRING;
397 sym.stringVal = value;
398 return NO_ERROR;
399 }
400
401 status_t makeSymbolPublic(const String8& name, const SourcePos& pos) {
402 if (!check_valid_symbol_name(name, pos, "symbol")) {
403 return BAD_VALUE;
404 }
405 AaptSymbolEntry& sym = edit_symbol(name, &pos);
406 sym.isPublic = true;
407 return NO_ERROR;
408 }
409
6415576e
DH
410 status_t makeSymbolJavaSymbol(const String8& name, const SourcePos& pos) {
411 if (!check_valid_symbol_name(name, pos, "symbol")) {
412 return BAD_VALUE;
413 }
414 AaptSymbolEntry& sym = edit_symbol(name, &pos);
415 sym.isJavaSymbol = true;
416 return NO_ERROR;
417 }
418
a534180c
TAOSP
419 void appendComment(const String8& name, const String16& comment, const SourcePos& pos) {
420 if (comment.size() <= 0) {
421 return;
422 }
423 AaptSymbolEntry& sym = edit_symbol(name, &pos);
424 if (sym.comment.size() == 0) {
425 sym.comment = comment;
426 } else {
427 sym.comment.append(String16("\n"));
428 sym.comment.append(comment);
429 }
430 }
431
432 void appendTypeComment(const String8& name, const String16& comment) {
433 if (comment.size() <= 0) {
434 return;
435 }
436 AaptSymbolEntry& sym = edit_symbol(name, NULL);
437 if (sym.typeComment.size() == 0) {
438 sym.typeComment = comment;
439 } else {
440 sym.typeComment.append(String16("\n"));
441 sym.typeComment.append(comment);
442 }
443 }
444
445 sp<AaptSymbols> addNestedSymbol(const String8& name, const SourcePos& pos) {
446 if (!check_valid_symbol_name(name, pos, "nested symbol")) {
447 return NULL;
448 }
449
450 sp<AaptSymbols> sym = mNestedSymbols.valueFor(name);
451 if (sym == NULL) {
452 sym = new AaptSymbols();
453 mNestedSymbols.add(name, sym);
454 }
455
456 return sym;
457 }
458
6415576e
DH
459 status_t applyJavaSymbols(const sp<AaptSymbols>& javaSymbols);
460
a534180c
TAOSP
461 const KeyedVector<String8, AaptSymbolEntry>& getSymbols() const
462 { return mSymbols; }
463 const DefaultKeyedVector<String8, sp<AaptSymbols> >& getNestedSymbols() const
464 { return mNestedSymbols; }
465
466 const String16& getComment(const String8& name) const
467 { return get_symbol(name).comment; }
468 const String16& getTypeComment(const String8& name) const
469 { return get_symbol(name).typeComment; }
470
471private:
472 bool check_valid_symbol_name(const String8& symbol, const SourcePos& pos, const char* label) {
473 if (valid_symbol_name(symbol)) {
474 return true;
475 }
476 pos.error("invalid %s: '%s'\n", label, symbol.string());
477 return false;
478 }
479 AaptSymbolEntry& edit_symbol(const String8& symbol, const SourcePos* pos) {
480 ssize_t i = mSymbols.indexOfKey(symbol);
481 if (i < 0) {
482 i = mSymbols.add(symbol, AaptSymbolEntry(symbol));
483 }
484 AaptSymbolEntry& sym = mSymbols.editValueAt(i);
485 if (pos != NULL && sym.sourcePos.line < 0) {
486 sym.sourcePos = *pos;
487 }
488 return sym;
489 }
490 const AaptSymbolEntry& get_symbol(const String8& symbol) const {
491 ssize_t i = mSymbols.indexOfKey(symbol);
492 if (i >= 0) {
493 return mSymbols.valueAt(i);
494 }
495 return mDefSymbol;
496 }
497
498 KeyedVector<String8, AaptSymbolEntry> mSymbols;
499 DefaultKeyedVector<String8, sp<AaptSymbols> > mNestedSymbols;
500 AaptSymbolEntry mDefSymbol;
501};
502
981d1579
MN
503class ResourceTypeSet : public RefBase,
504 public KeyedVector<String8,sp<AaptGroup> >
505{
506public:
507 ResourceTypeSet();
508};
509
52ffc169
JG
510// Storage for lists of fully qualified paths for
511// resources encountered during slurping.
512class FilePathStore : public RefBase,
513 public Vector<String8>
514{
515public:
516 FilePathStore();
517};
a534180c
TAOSP
518
519/**
520 * Asset hierarchy being operated on.
521 */
522class AaptAssets : public AaptDir
523{
524public:
e29f4ada 525 AaptAssets();
981d1579 526 virtual ~AaptAssets() { delete mRes; }
a534180c
TAOSP
527
528 const String8& getPackage() const { return mPackage; }
6415576e
DH
529 void setPackage(const String8& package) {
530 mPackage = package;
531 mSymbolsPrivatePackage = package;
532 mHavePrivateSymbols = false;
533 }
a534180c 534
e29f4ada
DH
535 const SortedVector<AaptGroupEntry>& getGroupEntries() const;
536
537 virtual status_t addFile(const String8& name, const sp<AaptGroup>& file);
a534180c
TAOSP
538
539 sp<AaptFile> addFile(const String8& filePath,
540 const AaptGroupEntry& entry,
541 const String8& srcDir,
542 sp<AaptGroup>* outGroup,
543 const String8& resType);
544
545 void addResource(const String8& leafName,
546 const String8& path,
547 const sp<AaptFile>& file,
548 const String8& resType);
549
a76631e8
DH
550 void addGroupEntry(const AaptGroupEntry& entry) { mGroupEntries.add(entry); }
551
a534180c
TAOSP
552 ssize_t slurpFromArgs(Bundle* bundle);
553
a534180c
TAOSP
554 sp<AaptSymbols> getSymbolsFor(const String8& name);
555
6415576e
DH
556 sp<AaptSymbols> getJavaSymbolsFor(const String8& name);
557
558 status_t applyJavaSymbols();
559
a534180c
TAOSP
560 const DefaultKeyedVector<String8, sp<AaptSymbols> >& getSymbols() const { return mSymbols; }
561
562 String8 getSymbolsPrivatePackage() const { return mSymbolsPrivatePackage; }
6415576e
DH
563 void setSymbolsPrivatePackage(const String8& pkg) {
564 mSymbolsPrivatePackage = pkg;
565 mHavePrivateSymbols = mSymbolsPrivatePackage != mPackage;
566 }
567
568 bool havePrivateSymbols() const { return mHavePrivateSymbols; }
569
570 bool isJavaSymbol(const AaptSymbolEntry& sym, bool includePrivate) const;
571
a534180c
TAOSP
572 status_t buildIncludedResources(Bundle* bundle);
573 status_t addIncludedResources(const sp<AaptFile>& file);
574 const ResTable& getIncludedResources() const;
575
e29f4ada 576 void print(const String8& prefix) const;
a534180c 577
e29f4ada
DH
578 inline const Vector<sp<AaptDir> >& resDirs() const { return mResDirs; }
579 sp<AaptDir> resDir(const String8& name) const;
a534180c
TAOSP
580
581 inline sp<AaptAssets> getOverlay() { return mOverlay; }
582 inline void setOverlay(sp<AaptAssets>& overlay) { mOverlay = overlay; }
583
584 inline KeyedVector<String8, sp<ResourceTypeSet> >* getResources() { return mRes; }
585 inline void
981d1579 586 setResources(KeyedVector<String8, sp<ResourceTypeSet> >* res) { delete mRes; mRes = res; }
a534180c 587
52ffc169
JG
588 inline sp<FilePathStore>& getFullResPaths() { return mFullResPaths; }
589 inline void
590 setFullResPaths(sp<FilePathStore>& res) { mFullResPaths = res; }
591
b5a473da
JG
592 inline sp<FilePathStore>& getFullAssetPaths() { return mFullAssetPaths; }
593 inline void
594 setFullAssetPaths(sp<FilePathStore>& res) { mFullAssetPaths = res; }
595
a534180c 596private:
e29f4ada
DH
597 virtual ssize_t slurpFullTree(Bundle* bundle,
598 const String8& srcDir,
599 const AaptGroupEntry& kind,
600 const String8& resType,
601 sp<FilePathStore>& fullResPaths);
602
603 ssize_t slurpResourceTree(Bundle* bundle, const String8& srcDir);
604 ssize_t slurpResourceZip(Bundle* bundle, const char* filename);
605
606 status_t filter(Bundle* bundle);
607
a534180c
TAOSP
608 String8 mPackage;
609 SortedVector<AaptGroupEntry> mGroupEntries;
610 DefaultKeyedVector<String8, sp<AaptSymbols> > mSymbols;
6415576e 611 DefaultKeyedVector<String8, sp<AaptSymbols> > mJavaSymbols;
a534180c 612 String8 mSymbolsPrivatePackage;
6415576e 613 bool mHavePrivateSymbols;
a534180c 614
e29f4ada
DH
615 Vector<sp<AaptDir> > mResDirs;
616
617 bool mChanged;
a534180c
TAOSP
618
619 bool mHaveIncludedAssets;
620 AssetManager mIncludedAssets;
621
622 sp<AaptAssets> mOverlay;
623 KeyedVector<String8, sp<ResourceTypeSet> >* mRes;
52ffc169
JG
624
625 sp<FilePathStore> mFullResPaths;
b5a473da 626 sp<FilePathStore> mFullAssetPaths;
a534180c
TAOSP
627};
628
629#endif // __AAPT_ASSETS_H
630