15c9fa2844c4f97b9358d547f947372f680c68dd1bungeman#!/usr/bin/python
25c9fa2844c4f97b9358d547f947372f680c68dd1bungeman
35c9fa2844c4f97b9358d547f947372f680c68dd1bungeman'''
45c9fa2844c4f97b9358d547f947372f680c68dd1bungemanCopyright 2015 Google Inc.
55c9fa2844c4f97b9358d547f947372f680c68dd1bungeman
65c9fa2844c4f97b9358d547f947372f680c68dd1bungemanUse of this source code is governed by a BSD-style license that can be
75c9fa2844c4f97b9358d547f947372f680c68dd1bungemanfound in the LICENSE file.
85c9fa2844c4f97b9358d547f947372f680c68dd1bungeman'''
95c9fa2844c4f97b9358d547f947372f680c68dd1bungeman
105c9fa2844c4f97b9358d547f947372f680c68dd1bungemanimport argparse
115c9fa2844c4f97b9358d547f947372f680c68dd1bungeman
125c9fa2844c4f97b9358d547f947372f680c68dd1bungeman
135c9fa2844c4f97b9358d547f947372f680c68dd1bungemandef bytes_from_file(f, chunksize=8192):
145c9fa2844c4f97b9358d547f947372f680c68dd1bungeman  while True:
155c9fa2844c4f97b9358d547f947372f680c68dd1bungeman    chunk = f.read(chunksize)
165c9fa2844c4f97b9358d547f947372f680c68dd1bungeman    if chunk:
175c9fa2844c4f97b9358d547f947372f680c68dd1bungeman      for b in chunk:
185c9fa2844c4f97b9358d547f947372f680c68dd1bungeman        yield ord(b)
195c9fa2844c4f97b9358d547f947372f680c68dd1bungeman    else:
205c9fa2844c4f97b9358d547f947372f680c68dd1bungeman      break
215c9fa2844c4f97b9358d547f947372f680c68dd1bungeman
225c9fa2844c4f97b9358d547f947372f680c68dd1bungeman
235c9fa2844c4f97b9358d547f947372f680c68dd1bungemandef main():
245c9fa2844c4f97b9358d547f947372f680c68dd1bungeman  parser = argparse.ArgumentParser(
255c9fa2844c4f97b9358d547f947372f680c68dd1bungeman      formatter_class=argparse.RawDescriptionHelpFormatter,
265c9fa2844c4f97b9358d547f947372f680c68dd1bungeman      description='Convert resource files to embedded read only data.',
275c9fa2844c4f97b9358d547f947372f680c68dd1bungeman      epilog='''The output (when compiled and linked) can be used as:
285c9fa2844c4f97b9358d547f947372f680c68dd1bungemanstruct SkEmbeddedResource {const uint8_t* data; const size_t size;};
295c9fa2844c4f97b9358d547f947372f680c68dd1bungemanstruct SkEmbeddedHeader {const SkEmbeddedResource* entries; const int count;};
305c9fa2844c4f97b9358d547f947372f680c68dd1bungemanextern "C" SkEmbeddedHeader const NAME;''')
315c9fa2844c4f97b9358d547f947372f680c68dd1bungeman  parser.add_argument('--align', default=1, type=int,
325c9fa2844c4f97b9358d547f947372f680c68dd1bungeman                      help='minimum alignment (in bytes) of resource data')
335c9fa2844c4f97b9358d547f947372f680c68dd1bungeman  parser.add_argument('--name', default='_resource', type=str,
345c9fa2844c4f97b9358d547f947372f680c68dd1bungeman                      help='the name of the c identifier to export')
355c9fa2844c4f97b9358d547f947372f680c68dd1bungeman  parser.add_argument('--input', required=True, type=argparse.FileType('rb'),
365c9fa2844c4f97b9358d547f947372f680c68dd1bungeman                      nargs='+', help='list of resource files to embed')
375c9fa2844c4f97b9358d547f947372f680c68dd1bungeman  parser.add_argument('--output', required=True, type=argparse.FileType('w'),
385c9fa2844c4f97b9358d547f947372f680c68dd1bungeman                      help='the name of the cpp file to output')
395c9fa2844c4f97b9358d547f947372f680c68dd1bungeman  args = parser.parse_args()
405c9fa2844c4f97b9358d547f947372f680c68dd1bungeman
415c9fa2844c4f97b9358d547f947372f680c68dd1bungeman  out = args.output.write;
425c9fa2844c4f97b9358d547f947372f680c68dd1bungeman  out('#include "SkTypes.h"\n')
435c9fa2844c4f97b9358d547f947372f680c68dd1bungeman
445c9fa2844c4f97b9358d547f947372f680c68dd1bungeman  # Write the resources.
455c9fa2844c4f97b9358d547f947372f680c68dd1bungeman  index = 0
465c9fa2844c4f97b9358d547f947372f680c68dd1bungeman  for f in args.input:
475c9fa2844c4f97b9358d547f947372f680c68dd1bungeman    out('static const uint8_t resource{0:d}[] SK_STRUCT_ALIGN({1:d}) = {{\n'
485c9fa2844c4f97b9358d547f947372f680c68dd1bungeman        .format(index, args.align))
495c9fa2844c4f97b9358d547f947372f680c68dd1bungeman    bytes_written = 0
505c9fa2844c4f97b9358d547f947372f680c68dd1bungeman    bytes_on_line = 0
515c9fa2844c4f97b9358d547f947372f680c68dd1bungeman    for b in bytes_from_file(f):
525c9fa2844c4f97b9358d547f947372f680c68dd1bungeman      out(hex(b) + ',')
535c9fa2844c4f97b9358d547f947372f680c68dd1bungeman      bytes_written += 1
545c9fa2844c4f97b9358d547f947372f680c68dd1bungeman      bytes_on_line += 1
555c9fa2844c4f97b9358d547f947372f680c68dd1bungeman      if bytes_on_line >= 32:
565c9fa2844c4f97b9358d547f947372f680c68dd1bungeman        out('\n')
575c9fa2844c4f97b9358d547f947372f680c68dd1bungeman        bytes_on_line = 0
585c9fa2844c4f97b9358d547f947372f680c68dd1bungeman    out('};\n')
595c9fa2844c4f97b9358d547f947372f680c68dd1bungeman    out('static const size_t resource{0:d}_size = {1:d};\n'
605c9fa2844c4f97b9358d547f947372f680c68dd1bungeman        .format(index, bytes_written))
615c9fa2844c4f97b9358d547f947372f680c68dd1bungeman    index += 1
625c9fa2844c4f97b9358d547f947372f680c68dd1bungeman
635c9fa2844c4f97b9358d547f947372f680c68dd1bungeman  # Write the resource entries.
645c9fa2844c4f97b9358d547f947372f680c68dd1bungeman  out('struct SkEmbeddedResource { const uint8_t* d; const size_t s; };\n')
655c9fa2844c4f97b9358d547f947372f680c68dd1bungeman  out('static const SkEmbeddedResource header[] = {\n')
665c9fa2844c4f97b9358d547f947372f680c68dd1bungeman  index = 0
675c9fa2844c4f97b9358d547f947372f680c68dd1bungeman  for f in args.input:
685c9fa2844c4f97b9358d547f947372f680c68dd1bungeman    out('  {{ resource{0:d}, resource{0:d}_size }},\n'.format(index))
695c9fa2844c4f97b9358d547f947372f680c68dd1bungeman    index += 1
705c9fa2844c4f97b9358d547f947372f680c68dd1bungeman  out('};\n')
715c9fa2844c4f97b9358d547f947372f680c68dd1bungeman  out('static const int header_count = {0:d};\n'.format(index))
725c9fa2844c4f97b9358d547f947372f680c68dd1bungeman
735c9fa2844c4f97b9358d547f947372f680c68dd1bungeman  # Export the resource header.
745c9fa2844c4f97b9358d547f947372f680c68dd1bungeman  out('struct SkEmbeddedHeader {const SkEmbeddedResource* e; const int c;};\n')
755c9fa2844c4f97b9358d547f947372f680c68dd1bungeman  out('extern "C" const SkEmbeddedHeader {0:s} = {{ header, header_count }};\n'
765c9fa2844c4f97b9358d547f947372f680c68dd1bungeman      .format(args.name))
775c9fa2844c4f97b9358d547f947372f680c68dd1bungeman
785c9fa2844c4f97b9358d547f947372f680c68dd1bungeman
795c9fa2844c4f97b9358d547f947372f680c68dd1bungemanif __name__ == "__main__":
805c9fa2844c4f97b9358d547f947372f680c68dd1bungeman  main()
81