# Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ''' PDC_GEN converts SVG images, SVG sequences, or JSON sequences to a PDC (Pebble Draw Command) binary format image or sequence. The PDC file format consists of a header, followed by the binary representation of a PDC image or sequence. The file header is as follows: Magic Word (4 bytes) - 'PDCI' for image, 'PDCS' for sequence Size (4 bytes) - size of PDC image or sequence following the header in bytes ''' import os import argparse import pebble_commands import svg2commands import json2commands def create_pdc_data_from_path(path, viewbox_size, verbose, duration, play_count, precise=False, raise_error=False): dir_name = path output = '' errors = [] if not os.path.exists(path): raise Exception("Invalid path") if verbose: print path + ":" if os.path.isfile(path): dir_name = os.path.dirname(path) frames = [] commands = [] if os.path.isfile(path): ext = os.path.splitext(path)[-1] if ext == '.json': # JSON file result = json2commands.parse_json_sequence(path, viewbox_size, precise, raise_error) if result: frames = result[0] errors += result[1] frame_duration = result[2] output = pebble_commands.serialize_sequence( frames, viewbox_size, frame_duration, play_count) elif ext == '.svg': # SVG file size, commands, error = svg2commands.parse_svg_image(path, verbose, precise, raise_error) if commands: output = pebble_commands.serialize_image(commands, size) if error: errors += [path] else: # SVG files # get all .svg files in directory result = svg2commands.parse_svg_sequence(dir_name, verbose, precise, raise_error) if result: frames = result[1] size = result[0] errors += result[2] output = pebble_commands.serialize_sequence(frames, size, duration, play_count) if verbose: if frames: pebble_commands.print_frames(frames) elif commands: pebble_commands.print_commands(commands) return output, errors def create_pdc_from_path(path, out_path, viewbox_size, verbose, duration, play_count, precise=False, raise_error=False): output, errors = create_pdc_data_from_path(path, viewbox_size, verbose, duration, play_count, precise=False, raise_error=False) if output != '': if out_path is None: if sequence: f = os.path.basename(dir_name.rstrip('/')) + '.pdc' else: base = os.path.basename(path) f = '.'.join(base.split('.')[:-1]) + '.pdc' out_path = os.path.join(dir_name, f) with open(out_path, 'w') as out_file: out_file.write(output) out_file.close() return errors def main(args): path = os.path.abspath(args.path) viewbox_size = (args.viewbox_x, args.viewbox_y) errors = create_pdc_from_path(path, args.output, viewbox_size, args.verbose, args.duration, args.play_count, args.precise) if errors: print "Errors in the following files or frames:" for ef in errors: print "\t" + str(ef) if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('path', type=str, help="Path to svg file or directory (with multiple svg files)") parser.add_argument('-o', '--output', type=str, help="Output file path (.pdc will be appended to file name if it is not included in the path " "specified") parser.add_argument('-v', '--verbose', action='store_true', help="Verbose output") parser.add_argument('-d', '--duration', type=int, default=33, help="Duration (ms) of each frame in a sequence (SVG sequence only) - default = 33ms") parser.add_argument('-c', '--play_count', type=int, default=1, help="Number of times the sequence should play - default = 1") parser.add_argument('-p', '--precise', action='store_true', help="Use sub-pixel precision for paths") parser.add_argument('-x', '--viewbox_x', help="Viewbox length (JSON sequence only)", type=int, default=json2commands.DISPLAY_DIM_X) parser.add_argument('-y', '--viewbox_y', help="Viewbox height (JSON sequence only)", type=int, default=json2commands.DISPLAY_DIM_Y) args = parser.parse_args() main(args)