--- /dev/null
+usage: main.py [-h] [-file FILE] [-dir DIR] [-output OUTPUT]\r
+\r
+options:\r
+ -h, --help 显示帮助信息。\r
+ -file FILE, -f FILE 指定待转化的离线表盘xml文件路径。\r
+ -dir DIR, -d DIR 指定待转化的文件夹路径。根据指定路径,转化文件夹下所有xml文件。\r
+ -output OUTPUT 指定转化后离线表盘打包资源所在路径\r
+\r
+example:\r
+windows: python .\main.py -dir .\instance\analogue_dial\r
+windows: python .\main.py -dir .\instance\kaleidoscope_dial
\ No newline at end of file
--- /dev/null
+#!/usr/bin/python\r
+# coding: utf-8\r
+import sys\r
+import struct\r
+from enum import Enum\r
+from ctypes import *\r
+\r
+class Point(Structure):\r
+ _fields_ = [\r
+ ('x', c_short),\r
+ ('y', c_short),\r
+ ]\r
+\r
+class Rect(Structure):\r
+ _fields_ = [\r
+ ('x', c_short),\r
+ ('y', c_short),\r
+ ('w', c_ushort),\r
+ ('h', c_ushort)\r
+ ]\r
+\r
+class ColorStop(Structure):\r
+ _fields_ = [\r
+ ('stop', c_float),\r
+ ('color', c_uint),\r
+ ]
\ No newline at end of file
--- /dev/null
+#!/usr/bin/python\r
+# coding: utf-8\r
+import os\r
+import re\r
+import struct\r
+import ctypes\r
+import sys\r
+from ctypes import *\r
+import xml.sax\r
+from enum import Enum\r
+import img_convert\r
+import video_convert\r
+from dial_static_img import DialStaticImg\r
+from dial_sequence_img import DialSequenceImg\r
+from dial_rotate_img import DialRotateImg\r
+from dial_option_img import DialOptionImg\r
+from dial_digital_img import DialDigitalImg\r
+from dial_label import DialLabel\r
+from dial_arc_label import DialArcLabel\r
+from dial_box_progress import DialBoxProgress\r
+from dial_arc_progress import DialArcProgress\r
+from dial_video import DialVideo\r
+from dial_click import DialClick\r
+from dial_kaleidoscope import DialKaleidoscope\r
+\r
+class DialHeader(Structure):\r
+ _fields_ = [\r
+ ('dialName', c_char * 16),\r
+ ('width', c_short),\r
+ ('height', c_short),\r
+ ('version', c_char * 16),\r
+ ('previewImgId', c_ushort),\r
+ ('description', c_char * 128),\r
+ ('imgoffset', c_uint),\r
+ ('period', c_ubyte),\r
+ ('dialViewCount', c_ubyte),\r
+ ('displayCapabiliy', c_ubyte),\r
+ ('ambientPeriod', c_ubyte),\r
+ ]\r
+ _DIAL_DEFAULT_MAX_WIDTH = 960\r
+ _DIAL_DEFAULT_MAX_HEIGHT = 960\r
+\r
+ def __init__(self):\r
+ self.imgoffset = 0\r
+ self.dialViewCount = 0\r
+ self.period = 0\r
+ self.displayCapabiliy = 0\r
+ self.ambientPeriod = 0\r
+ self.viewType = []\r
+ self.viewPt = []\r
+\r
+ def parse_attributes(self, attributes):\r
+ title = attributes["title"]\r
+ self.dialName = bytes(title, encoding = "utf8")\r
+\r
+ description = attributes["description"]\r
+ self.description = bytes(description, encoding = "utf8")\r
+\r
+ version = attributes["version"]\r
+ self.version = bytes(version, encoding = "utf8")\r
+\r
+ self._parse_size_attr(attributes["size"])\r
+\r
+ previewStr = attributes["preview_img"]\r
+ self.previewImgId = img_convert.instance.convert_img(previewStr)\r
+\r
+ for attr in attributes.getNames():\r
+ if attr == "tile_width":\r
+ tile_width = int(attributes["tile_width"])\r
+ img_convert.instance.set_tile_width(tile_width)\r
+ elif attr == "ambient_period":\r
+ period_suppor_value = {1, 10, 30, 60}\r
+ self.ambientPeriod = int(attributes["ambient_period"])\r
+ if self.ambientPeriod not in period_suppor_value:\r
+ self.ambientPeriod = 0\r
+ print("[WARNING]:label image period value not support, using defalut value 0")\r
+\r
+\r
+ def add_view(self, viewObj, viewType):\r
+ self.viewPt.append(viewObj)\r
+ self.viewType.append(viewType)\r
+ self.dialViewCount += 1\r
+\r
+ def get_bytes(self):\r
+ ret = bytes(self)\r
+ for index in range(self.dialViewCount):\r
+ ret += struct.pack('@b', self.viewType[index])\r
+ return ret\r
+\r
+ def get_size(self):\r
+ return sizeof(self) + sizeof(c_ubyte) * self.dialViewCount\r
+\r
+ def _parse_size_attr(self, input_size):\r
+ input_width,input_height = input_size.split(' ')\r
+ width = int(input_width)\r
+ if width <= 0 or width > DialHeader._DIAL_DEFAULT_MAX_WIDTH :\r
+ print(f"[ERR]:dial size width out of range, (0, {DialHeader._DIAL_DEFAULT_MAX_WIDTH}], value:{width}")\r
+ sys.exit(1)\r
+ self.width = width\r
+\r
+ height = int(input_height)\r
+ if height <= 0 or height > DialHeader._DIAL_DEFAULT_MAX_HEIGHT :\r
+ print(f"[ERR]:dial size height out of range, (0, {DialHeader._DIAL_DEFAULT_MAX_HEIGHT}], value:{height}")\r
+ sys.exit(1)\r
+ self.height = height\r
+\r
+class DialConvertTool(xml.sax.ContentHandler):\r
+ parser = xml.sax.make_parser()\r
+ DIAL_STATIC_IMG_TYPE = 0\r
+ DIAL_SEQUENCE_IMG_TYPE = 1\r
+ DIAL_ROTATE_IMG_TYPE = 2\r
+ DIAL_OPTION_IMG_TYPE = 3\r
+ DIAL_DIGITAL_IMG_TYPE = 4\r
+ DIAL_LABEL_TYPE = 5\r
+ DIAL_ARC_LABEL_TYPE = 6\r
+ DIAL_BOX_PROGRESS_TYPE = 7\r
+ DIAL_ARC_PROGRESS_TYPE = 8\r
+ DIAL_VIDEO_TYPE = 9\r
+ DIAL_CLICK_TYPE = 10\r
+ DIAL_KALEIDOSCCOPE_TYPE = 11\r
+\r
+ def __init__(self):\r
+ self.inFile = ""\r
+ self.outPath = ""\r
+ self.header = DialHeader()\r
+ self.parser.setFeature(xml.sax.handler.feature_namespaces, 0)\r
+ self.parser.setContentHandler(self)\r
+\r
+ def startElement(self, tag, attributes):\r
+ viewTypeArray = []\r
+ if tag == "dial":\r
+ self.header.parse_attributes(attributes)\r
+ elif tag == "static_img":\r
+ view = DialStaticImg()\r
+ view.parse_attributes(attributes)\r
+ self.header.add_view(view, self.DIAL_STATIC_IMG_TYPE)\r
+ elif tag == "sequence_img":\r
+ view = DialSequenceImg()\r
+ view.parse_attributes(attributes)\r
+ self.header.add_view(view, self.DIAL_SEQUENCE_IMG_TYPE)\r
+ elif tag == "rotate_img":\r
+ view = DialRotateImg()\r
+ view.parse_attributes(attributes)\r
+ self.header.add_view(view, self.DIAL_ROTATE_IMG_TYPE)\r
+ elif tag == "option_img":\r
+ view = DialOptionImg()\r
+ view.parse_attributes(attributes)\r
+ self.header.add_view(view, self.DIAL_OPTION_IMG_TYPE)\r
+ elif tag == "digital_img":\r
+ view = DialDigitalImg()\r
+ view.parse_attributes(attributes)\r
+ self.header.add_view(view, self.DIAL_DIGITAL_IMG_TYPE)\r
+ elif tag == "label":\r
+ view = DialLabel()\r
+ view.parse_attributes(attributes)\r
+ self.header.add_view(view, self.DIAL_LABEL_TYPE)\r
+ elif tag == "arc_label":\r
+ view = DialArcLabel()\r
+ view.parse_attributes(attributes)\r
+ self.header.add_view(view, self.DIAL_ARC_LABEL_TYPE)\r
+ elif tag == "box_progress":\r
+ view = DialBoxProgress()\r
+ view.parse_attributes(attributes)\r
+ self.header.add_view(view, self.DIAL_BOX_PROGRESS_TYPE)\r
+ elif tag == "arc_progress":\r
+ view = DialArcProgress()\r
+ view.parse_attributes(attributes)\r
+ self.header.add_view(view, self.DIAL_ARC_PROGRESS_TYPE)\r
+ elif tag == "video":\r
+ view = DialVideo()\r
+ view.parse_attributes(attributes)\r
+ self.header.add_view(view, self.DIAL_VIDEO_TYPE)\r
+ elif tag == "click":\r
+ view = DialClick()\r
+ view.parse_attributes(attributes)\r
+ self.header.add_view(view, self.DIAL_CLICK_TYPE)\r
+ elif tag == "kaleidoscope":\r
+ view = DialKaleidoscope()\r
+ view.parse_attributes(attributes)\r
+ self.header.add_view(view, self.DIAL_KALEIDOSCCOPE_TYPE)\r
+\r
+ def endElement(self, tag):\r
+ if tag == "dial":\r
+ # create & open dstfile\r
+ outputfile = self.outPath + "/" + os.path.basename(self.inFile)[:-3] + "bin"\r
+ fb = open(outputfile, 'wb')\r
+ os.chmod(outputfile, 0o0755)\r
+ self._write_data_to_bin(fb)\r
+ fb.close()\r
+\r
+ def convert_xml_to_output(self, inFile, outPath):\r
+ self.inFile = inFile\r
+ self.outPath = outPath\r
+ self.parser.parse(inFile)\r
+\r
+ def _write_data_to_bin(self, fb):\r
+ self.header.imgoffset += self.header.get_size()\r
+ aod_only, normal_only = 0, 0\r
+ for view in self.header.viewPt:\r
+ if self.header.period < view.period:\r
+ self.header.period = view.period\r
+ if view.displayMode == 1:\r
+ aod_only = aod_only + 1\r
+ elif view.displayMode == 2:\r
+ aod_only = aod_only + 1\r
+ normal_only = normal_only + 1\r
+ else:\r
+ normal_only = normal_only + 1\r
+ self.header.imgoffset += view.get_size()\r
+ if normal_only > 0 and aod_only > 0:\r
+ self.header.displayCapabiliy = 2\r
+ elif normal_only > 0 and aod_only == 0:\r
+ self.header.displayCapabiliy = 0\r
+ else:\r
+ self.header.displayCapabiliy = 1\r
+\r
+ fb.write(self.header.get_bytes())\r
+ for view in self.header.viewPt:\r
+ if isinstance(view, DialVideo):\r
+ view.offset += self.header.imgoffset + img_convert.instance.get_size()\r
+ fb.write(view.get_bytes())\r
+ img_convert.instance.write_data_to_bin(fb)\r
+ video_convert.instance.write_data_to_bin(fb)\r
--- /dev/null
+#!/usr/bin/python\r
+# coding: utf-8\r
+import sys\r
+import struct\r
+import numpy as np\r
+from xml.dom.minidom import parse\r
+from ctypes import *\r
+from common_types import Point\r
+\r
+class DialArcLabel(Structure):\r
+ _fields_ = [\r
+ ('align', c_ubyte),\r
+ ('fontSize', c_ubyte),\r
+ ('center', Point),\r
+ ('radius', c_ushort),\r
+ ('rotateStart', c_short),\r
+ ('rotaeteEnd', c_short),\r
+ ('color', c_uint),\r
+ ('fontName', c_char * 64),\r
+ ('text', c_char * 64),\r
+ ('bindData', c_short),\r
+ ('isPeriodic', c_bool),\r
+ ('displayMode', c_ubyte),\r
+ ('isAmbientPeriodic', c_bool)\r
+ ]\r
+ def __init__(self):\r
+ self.period = 0\r
+ self.isPeriodic = False\r
+ self.displayMode = 0\r
+ self.isAmbientPeriodic = False\r
+\r
+ def parse_attributes(self, attributes):\r
+ alignStr = attributes["align"]\r
+ if alignStr == "bottom":\r
+ self.align = 4\r
+ elif alignStr == "top":\r
+ self.align = 3\r
+ elif alignStr == "center":\r
+ self.align = 2\r
+ elif alignStr == "right":\r
+ self.align = 1\r
+ elif alignStr == "left":\r
+ self.align = 0\r
+ else:\r
+ self.align = 0\r
+ print("[WARNING] arc label align value input error, using defalut value")\r
+\r
+ self.fontSize = int(attributes["font_size"])\r
+ if self.fontSize < np.iinfo(np.int16).min or self.fontSize > np.iinfo(np.int16).max:\r
+ print("[ERR]:label font size out of range")\r
+ sys.exit(1)\r
+\r
+ x,y = attributes["center"].split(" ")\r
+ self.center.x = int(x)\r
+ if self.center.x < np.iinfo(np.int16).min or self.center.x > np.iinfo(np.int16).max:\r
+ print("[ERR]:arc label center x out of range")\r
+ sys.exit(1)\r
+ self.center.y = int(y)\r
+ if self.center.y < np.iinfo(np.int16).min or self.center.y > np.iinfo(np.int16).max:\r
+ print("[ERR]:arc label center y out of range")\r
+ sys.exit(1)\r
+\r
+ self.radius = int(attributes["radius"])\r
+ if self.radius < 0 or self.radius > np.iinfo(np.int16).max:\r
+ print("[ERR]:arc label radius out of range")\r
+ sys.exit(1)\r
+\r
+ self.rotateStart = int(attributes["start_angle"])\r
+ self.rotaeteEnd = int(attributes["end_angle"])\r
+\r
+ self.color = int(attributes["color"], 16)\r
+ self.fontName = bytes(attributes["font"], encoding = "utf8")\r
+ self.text = bytes(attributes["text"], encoding = "utf8")\r
+ for attr in attributes.getNames():\r
+ if attr == "bind_data":\r
+ self.bindData = int(attributes["bind_data"])\r
+ if self.bindData < 0 or self.bindData > np.iinfo(np.int16).max:\r
+ print("[ERR]:arc label bind data out of range")\r
+ sys.exit(1)\r
+ elif attr == "period":\r
+ period_suppor_value = {1, 10, 30, 60}\r
+ self.period = int(attributes["period"])\r
+ if self.period == 0:\r
+ self.isPeriodic = False\r
+ elif self.period not in period_suppor_value:\r
+ self.period = 0\r
+ print("[WARNING]:arc label period value not support, using defalut value 0")\r
+ else:\r
+ self.isPeriodic = True\r
+\r
+ if "display_mode" in attributes.getNames():\r
+ display_mode = attributes["display_mode"]\r
+ if display_mode == "normal":\r
+ self.displayMode = 0\r
+ elif display_mode == "ambient":\r
+ self.displayMode= 1\r
+ elif display_mode == "always":\r
+ self.displayMode= 2\r
+ if self.displayMode != 0 :\r
+ if "ambient_periodic" in attributes.getNames():\r
+ if attributes["ambient_periodic"] == "true":\r
+ self.isAmbientPeriodic = True\r
+\r
+ if self.isPeriodic != 0 and self.bindData == 0:\r
+ print("[ERR]:[bind_data] is not set, [period] cannot be set")\r
+ sys.exit(1)\r
+\r
+ def get_bytes(self):\r
+ return bytes(self)\r
+\r
+ def get_size(self):\r
+ return sizeof(self)
\ No newline at end of file
--- /dev/null
+#!/usr/bin/python\r
+# coding: utf-8\r
+import sys\r
+import struct\r
+import numpy as np\r
+from xml.dom.minidom import parse\r
+from ctypes import *\r
+from common_types import Rect\r
+from common_types import ColorStop\r
+import img_convert\r
+\r
+class ProgressUnion(Union):\r
+ _fields_ = [\r
+ ('stopCount', c_ubyte),\r
+ ('imgId', c_ushort),\r
+ ('color', c_uint),\r
+ ]\r
+\r
+class DialArcProgress(Structure):\r
+ _fields_ = [\r
+ ('cap', c_ubyte),\r
+ ('isPeriodic', c_bool),\r
+ ('radius', c_ushort),\r
+ ('startAngle', c_ushort),\r
+ ('endAngle', c_ushort),\r
+ ('lineWidth', c_ushort),\r
+ ('bindData', c_short),\r
+ ('bgColor', c_uint),\r
+ ('type', c_ubyte),\r
+ ('rect', Rect),\r
+ ('unionValue', ProgressUnion),\r
+ ('displayMode', c_ubyte),\r
+ ('isAmbientPeriodic', c_bool)\r
+ ]\r
+\r
+ def __init__(self):\r
+ self.stop = []\r
+ self.period = 0\r
+ self.isPeriodic = False\r
+ self.displayMode = 0\r
+ self.isAmbientPeriodic = False\r
+\r
+ def parse_attributes(self, attributes):\r
+ x,y,w,h = attributes["rect"].split(" ")\r
+ self.rect.x = int(x)\r
+ if self.rect.x < np.iinfo(np.int16).min or self.rect.x > np.iinfo(np.int16).max:\r
+ print("[ERR]:arc progress rect x out of range")\r
+ sys.exit(1)\r
+ self.rect.y = int(y)\r
+ if self.rect.y < np.iinfo(np.int16).min or self.rect.y > np.iinfo(np.int16).max:\r
+ print("[ERR]:arc progress rect y out of range")\r
+ sys.exit(1)\r
+ self.rect.w = int(w)\r
+ if self.rect.w < np.iinfo(np.int16).min or self.rect.w > np.iinfo(np.int16).max:\r
+ print("[ERR]:arc progress rect w out of range")\r
+ sys.exit(1)\r
+ self.rect.h = int(h)\r
+ if self.rect.h < np.iinfo(np.int16).min or self.rect.h > np.iinfo(np.int16).max:\r
+ print("[ERR]:arc progress rect h out of range")\r
+ sys.exit(1)\r
+\r
+ cap = attributes["cap_type"]\r
+ if cap == "round":\r
+ self.cap = 1\r
+ else:\r
+ self.cap = 0\r
+\r
+ self.radius = int(attributes["radius"])\r
+ if self.radius < 0 or self.radius > np.iinfo(np.int16).max:\r
+ print("[ERR]:arc progress radius out of range")\r
+ sys.exit(1)\r
+\r
+ self.startAngle = int(attributes["start_angle"])\r
+ self.endAngle = int(attributes["end_angle"])\r
+\r
+ self.lineWidth = int(attributes["line_width"])\r
+ if self.lineWidth < 0 or self.lineWidth > np.iinfo(np.int16).max:\r
+ print("[ERR]:arc progress lineWidth out of range")\r
+ sys.exit(1)\r
+\r
+ self.bindData = int(attributes["bind_data"])\r
+ if self.bindData < 0 or self.bindData > np.iinfo(np.int16).max:\r
+ print("[ERR]:arc progress bind data out of range")\r
+ sys.exit(1)\r
+\r
+ attrList = attributes.getNames()\r
+ for attr in attrList:\r
+ if attr == "img_name":\r
+ self.unionValue.imgId = img_convert.instance.convert_img(attributes["img_name"])\r
+ self.type = 0\r
+ break\r
+ elif attr == "color":\r
+ self.unionValue.color = int(attributes["color"], 16)\r
+ self.type = 1\r
+ break\r
+ elif attr == "gradient_colors":\r
+ self.type = 2\r
+ stopList = attributes["gradient_stops"].split(" ")\r
+ colorList = attributes["gradient_colors"].split(" ")\r
+ if len(stopList) != len(colorList):\r
+ print("[ERROR]:[gradient_stops] attr not equal [colorList] attr")\r
+ self.unionValue.stopCount = min(len(colorList), len(stopList))\r
+ for index in range(self.unionValue.stopCount):\r
+ colorStop = ColorStop()\r
+ colorStop.stop = float(stopList[index])\r
+ colorStop.color = int(colorList[index], 16)\r
+ self.stop.append(colorStop)\r
+ break\r
+\r
+ if "display_mode" in attributes.getNames():\r
+ display_mode = attributes["display_mode"]\r
+ if display_mode == "normal":\r
+ self.displayMode = 0\r
+ elif display_mode == "ambient":\r
+ self.displayMode= 1\r
+ elif display_mode == "always":\r
+ self.displayMode= 2\r
+ if self.displayMode != 0 :\r
+ if "ambient_periodic" in attributes.getNames():\r
+ if attributes["ambient_periodic"] == "true":\r
+ self.isAmbientPeriodic = True\r
+\r
+ if "period" in attrList:\r
+ period_suppor_value = {1, 10, 30, 60}\r
+ self.period = int(attributes["period"])\r
+ if self.period == 0:\r
+ self.isPeriodic = False\r
+ elif self.period not in period_suppor_value:\r
+ self.period = 0\r
+ print("[WARNING]:label image period value not support, using defalut value 0")\r
+ else:\r
+ self.isPeriodic = True\r
+\r
+ if "background_color" in attrList:\r
+ self.bgColor = int(attributes["background_color"], 16)\r
+\r
+ def get_bytes(self):\r
+ ret = bytes(self)\r
+ if self.type == 2:\r
+ for stop in self.stop:\r
+ ret += bytes(stop)\r
+ return ret\r
+\r
+ def get_size(self):\r
+ ret = sizeof(self)\r
+ if self.type == 2:\r
+ for stop in self.stop:\r
+ ret += sizeof(stop)\r
+ return ret
\ No newline at end of file
--- /dev/null
+#!/usr/bin/python\r
+# coding: utf-8\r
+import sys\r
+import struct\r
+import numpy as np\r
+from xml.dom.minidom import parse\r
+from ctypes import *\r
+from common_types import Rect\r
+from common_types import ColorStop\r
+import img_convert\r
+\r
+class ProgressUnion(Union):\r
+ _fields_ = [\r
+ ('stopCount', c_ubyte),\r
+ ('imgId', c_ushort),\r
+ ('color', c_uint),\r
+ ]\r
+\r
+class DialBoxProgress(Structure):\r
+ _fields_ = [\r
+ ('cap', c_ubyte),\r
+ ('direction', c_ubyte),\r
+ ('isPeriodic', c_bool),\r
+ ('bindData', c_short),\r
+ ('bgColor', c_uint),\r
+ ('type', c_ubyte),\r
+ ('rect', Rect),\r
+ ('unionValue', ProgressUnion),\r
+ ('displayMode', c_ubyte),\r
+ ('isAmbientPeriodic', c_bool)\r
+ ]\r
+\r
+ def __init__(self):\r
+ self.stop = []\r
+ self.isPeriodic = False\r
+ self.period = 0\r
+ self.displayMode = 0\r
+ self.isAmbientPeriodic = False\r
+\r
+ def parse_attributes(self, attributes):\r
+ x,y,w,h = attributes["rect"].split(" ")\r
+ self.rect.x = int(x)\r
+ if self.rect.x < np.iinfo(np.int16).min or self.rect.x > np.iinfo(np.int16).max:\r
+ print("[ERR]:box progress rect x out of range")\r
+ sys.exit(1)\r
+ self.rect.y = int(y)\r
+ if self.rect.y < np.iinfo(np.int16).min or self.rect.y > np.iinfo(np.int16).max:\r
+ print("[ERR]:box progress rect y out of range")\r
+ sys.exit(1)\r
+ self.rect.w = int(w)\r
+ if self.rect.w < np.iinfo(np.int16).min or self.rect.w > np.iinfo(np.int16).max:\r
+ print("[ERR]:box progress rect w out of range")\r
+ sys.exit(1)\r
+ self.rect.h = int(h)\r
+ if self.rect.h < np.iinfo(np.int16).min or self.rect.h > np.iinfo(np.int16).max:\r
+ print("[ERR]:box progress rect h out of range")\r
+ sys.exit(1)\r
+\r
+ cap = attributes["cap_type"]\r
+ if cap == "round":\r
+ self.cap = 1\r
+ else:\r
+ self.cap = 0\r
+\r
+ direction = attributes["direction"]\r
+ if direction == "left_to_right":\r
+ self.direction = 0\r
+ elif direction == "right_to_left":\r
+ self.direction = 1\r
+ elif direction == "top_to_bottom":\r
+ self.direction = 2\r
+ elif direction == "bottom_to_top":\r
+ self.direction = 3\r
+ else:\r
+ self.direction = 0\r
+ print("[WARNING]:box progress direction set error, using defalut value")\r
+\r
+ self.bindData = int(attributes["bind_data"])\r
+ if self.bindData < 0 or self.bindData > np.iinfo(np.int16).max:\r
+ print("[ERR]:box progress bind data out of range")\r
+ sys.exit(1)\r
+\r
+ attrList = attributes.getNames()\r
+ for attr in attrList:\r
+ if attr == "img_name":\r
+ self.unionValue.imgId = img_convert.instance.convert_img(attributes["img_name"])\r
+ self.type = 0\r
+ break\r
+ elif attr == "color":\r
+ self.unionValue.color = int(attributes["color"], 16)\r
+ self.type = 1\r
+ break\r
+ elif attr == "gradient_colors":\r
+ stopList = attributes["gradient_stops"].split(" ")\r
+ colorList = attributes["gradient_colors"].split(" ")\r
+ if len(stopList) != len(colorList):\r
+ print("[ERROR]:[gradient_stops] attr not equal [colorList] attr")\r
+ self.unionValue.stopCount = min(len(colorList), len(stopList))\r
+ for index in range(self.unionValue.stopCount):\r
+ colorStop = ColorStop()\r
+ colorStop.stop = float(stopList[index])\r
+ colorStop.color = int(colorList[index], 16)\r
+ self.stop.append(colorStop)\r
+ self.type = 2\r
+ break\r
+\r
+ if "display_mode" in attributes.getNames():\r
+ display_mode = attributes["display_mode"]\r
+ if display_mode == "normal":\r
+ self.displayMode = 0\r
+ elif display_mode == "ambient":\r
+ self.displayMode= 1\r
+ elif display_mode == "always":\r
+ self.displayMode= 2\r
+ if self.displayMode != 0 :\r
+ if "ambient_periodic" in attributes.getNames():\r
+ if attributes["ambient_periodic"] == "true":\r
+ self.isAmbientPeriodic = True\r
+\r
+ if "period" in attrList:\r
+ period_suppor_value = {1, 10, 30, 60}\r
+ self.period = int(attributes["period"])\r
+ if self.period == 0:\r
+ self.isPeriodic = False\r
+ elif self.period not in period_suppor_value:\r
+ self.period = 0\r
+ print("[WARNING]:label image period value not support, using defalut value 0")\r
+ else:\r
+ self.isPeriodic = True\r
+\r
+ if "background_color" in attrList:\r
+ self.bgColor = int(attributes["background_color"], 16)\r
+\r
+ def get_bytes(self):\r
+ ret = bytes(self)\r
+ if self.type == 2:\r
+ for stop in self.stop:\r
+ ret += bytes(stop)\r
+ return ret\r
+\r
+ def get_size(self):\r
+ ret = sizeof(self)\r
+ if self.type == 2:\r
+ for stop in self.stop:\r
+ ret += sizeof(stop)\r
+ return ret
\ No newline at end of file
--- /dev/null
+#!/usr/bin/python\r
+# coding: utf-8\r
+import sys\r
+import struct\r
+import numpy as np\r
+from xml.dom.minidom import parse\r
+from ctypes import *\r
+from common_types import Rect\r
+\r
+class ClickTypeUnion(Union):\r
+ _fields_ = [\r
+ ('sliceId', c_uint),\r
+ ('bundleName', c_char * 64)\r
+ ]\r
+\r
+class DialClick(Structure):\r
+ _fields_ = [\r
+ ('type', c_ubyte),\r
+ ('rect', Rect),\r
+ ('unionType', ClickTypeUnion),\r
+ ('displayMode', c_ubyte)\r
+ ]\r
+\r
+ def __init__(self):\r
+ self.period = 0\r
+ self.displayMode = 0\r
+\r
+ def parse_attributes(self, attributes):\r
+ x,y,w,h = attributes["rect"].split(" ")\r
+ self.rect.x = int(x)\r
+ if self.rect.x < np.iinfo(np.int16).min or self.rect.x > np.iinfo(np.int16).max:\r
+ print("[ERR]:click rect x out of range")\r
+ sys.exit(1)\r
+ self.rect.y = int(y)\r
+ if self.rect.y < np.iinfo(np.int16).min or self.rect.y > np.iinfo(np.int16).max:\r
+ print("[ERR]:click rect y out of range")\r
+ sys.exit(1)\r
+ self.rect.w = int(w)\r
+ if self.rect.w < np.iinfo(np.int16).min or self.rect.w > np.iinfo(np.int16).max:\r
+ print("[ERR]:click rect w out of range")\r
+ sys.exit(1)\r
+ self.rect.h = int(h)\r
+ if self.rect.h < np.iinfo(np.int16).min or self.rect.h > np.iinfo(np.int16).max:\r
+ print("[ERR]:click rect h out of range")\r
+ sys.exit(1)\r
+\r
+ for attr in attributes.getNames():\r
+ if attr == "action_slice":\r
+ self.unionType.sliceId = int(attributes["action_slice"])\r
+ self.type = 0\r
+ break\r
+ elif attr == "action_bundle":\r
+ self.unionType.bundleName = bytes(attributes["action_bundle"], encoding = "utf8")\r
+ self.type = 1\r
+ break\r
+\r
+ if "display_mode" in attributes.getNames():\r
+ display_mode = attributes["display_mode"]\r
+ if display_mode == "normal":\r
+ self.displayMode = 0\r
+ elif display_mode == "ambient":\r
+ self.displayMode= 1\r
+ elif display_mode == "always":\r
+ self.displayMode= 2\r
+\r
+ def get_bytes(self):\r
+ return bytes(self)\r
+\r
+ def get_size(self):\r
+ return sizeof(self)
\ No newline at end of file
--- /dev/null
+#!/usr/bin/python\r
+# coding: utf-8\r
+import sys\r
+import struct\r
+import numpy as np\r
+from xml.dom.minidom import parse\r
+from ctypes import *\r
+from common_types import Point\r
+import img_convert\r
+\r
+class DialDigitalImg(Structure):\r
+ _fields_ = [\r
+ ('alignType', c_ubyte, 4),\r
+ ('integerLength', c_ubyte, 4),\r
+ ('decimalPrecision', c_ubyte),\r
+ ('imgIds', c_ushort * 10),\r
+ ('signImgId', c_ushort),\r
+ ('decimalPointImgId', c_ushort),\r
+ ('space', c_ushort),\r
+ ('alignPosition', Point),\r
+ ('bindData', c_short),\r
+ ('isPeriodic', c_bool),\r
+ ('displayMode', c_ubyte),\r
+ ('isAmbientPeriodic', c_bool)\r
+ ]\r
+\r
+ def __init__(self):\r
+ self.period = 0\r
+ self.isPeriodic = False\r
+ self.displayMode = 0\r
+ self.isAmbientPeriodic = False\r
+\r
+ def parse_attributes(self, attributes):\r
+ imgNames = attributes["img_names"].split(",")\r
+ length = len(imgNames)\r
+ if length < 10:\r
+ print("[ERR]:tag:[digital_img] attr[img_names] less than 10!")\r
+ sys.exit(1)\r
+ else:\r
+ for index in range(10):\r
+ self.imgIds[index] = img_convert.instance.convert_img(imgNames[index])\r
+\r
+ self.space = int(attributes["space"])\r
+ if self.space < 0 or self.space > np.iinfo(np.int16).max:\r
+ print("[ERR]:digital image space out of range")\r
+ sys.exit(1)\r
+\r
+ alignStr = attributes["align"]\r
+ if alignStr == "right":\r
+ self.alignType = 2\r
+ elif alignStr == "center":\r
+ self.alignType = 1\r
+ elif alignStr == "left":\r
+ self.alignType = 0\r
+ else:\r
+ print("[ERR]:digital image align not support")\r
+\r
+ align_pos_x,align_pos_y = attributes["align_pos"].split(" ")\r
+ align_x = int(align_pos_x)\r
+ if align_x < np.iinfo(np.int16).min or align_x > np.iinfo(np.int16).max:\r
+ print("[ERR]:digital image align x out of range")\r
+ sys.exit(1)\r
+ self.alignPosition.x = align_x\r
+\r
+ align_y = int(align_pos_y)\r
+ if align_y < np.iinfo(np.int16).min or align_y > np.iinfo(np.int16).max:\r
+ print("[ERR]:digital image align y out of range")\r
+ sys.exit(1)\r
+ self.alignPosition.y = align_y\r
+\r
+ self.bindData = int(attributes["bind_data"])\r
+ if self.bindData < 0 or self.bindData > np.iinfo(np.int16).max:\r
+ print("[ERR]:digital image bind data out of range")\r
+ sys.exit(1)\r
+\r
+ for attr in attributes.getNames():\r
+ if attr == "sign_img_name":\r
+ signImgName = attributes["sign_img_name"]\r
+ self.signImgId = img_convert.instance.convert_img(signImgName)\r
+ elif attr == "integer_length":\r
+ self.integerLength = int(attributes["integer_length"])\r
+ if self.integerLength < 0 or self.integerLength > np.iinfo(np.uint8).max:\r
+ print("[ERR]:digital image integer length out of range")\r
+ sys.exit(1)\r
+ elif attr == "img_decimal_point":\r
+ decimalPointImgName = attributes["img_decimal_point"]\r
+ self.decimalPointImgId = img_convert.instance.convert_img(decimalPointImgName)\r
+ elif attr == "decimal_precision":\r
+ self.decimalPrecision = int(attributes["decimal_precision"])\r
+ if self.decimalPrecision < 0 or self.decimalPrecision > np.iinfo(np.uint8).max:\r
+ print("[ERR]:digital image decimal precision out of range")\r
+ sys.exit(1)\r
+ elif attr == "period":\r
+ period_suppor_value = {1, 10, 30, 60}\r
+ self.period = int(attributes["period"])\r
+ if self.period == 0:\r
+ self.isPeriodic = False\r
+ elif self.period not in period_suppor_value:\r
+ self.period = 0\r
+ print("[WARNING]:digital image period value not support, using defalut value 0")\r
+ else:\r
+ self.isPeriodic = True\r
+\r
+ if "display_mode" in attributes.getNames():\r
+ display_mode = attributes["display_mode"]\r
+ if display_mode == "normal":\r
+ self.displayMode = 0\r
+ elif display_mode == "ambient":\r
+ self.displayMode= 1\r
+ elif display_mode == "always":\r
+ self.displayMode= 2\r
+ if self.displayMode != 0 :\r
+ if "ambient_periodic" in attributes.getNames():\r
+ if attributes["ambient_periodic"] == "true":\r
+ self.isAmbientPeriodic = True\r
+\r
+ def get_bytes(self):\r
+ return bytes(self)\r
+\r
+ def get_size(self):\r
+ return sizeof(self)
\ No newline at end of file
--- /dev/null
+#!/usr/bin/python\r
+# coding: utf-8\r
+import sys\r
+import struct\r
+from xml.dom.minidom import parse\r
+from ctypes import *\r
+import img_convert\r
+\r
+class DialKaleidoscope(Structure):\r
+ _fields_ = [\r
+ ('imgId', c_ushort),\r
+ ('rotateEventFactor', c_float),\r
+ ('rotateAnimatorValue', c_float),\r
+ ('displayMode', c_ubyte)\r
+ ]\r
+\r
+ def __init__(self):\r
+ self.imgId = 0\r
+ self.rotateEventFactor = 1.0\r
+ self.rotateAnimatorValue = 0.0\r
+ self.period = 0\r
+ self.displayMode = 0\r
+\r
+ def parse_attributes(self, attributes):\r
+ self.imgId = img_convert.instance.convert_img(attributes["img_name"])\r
+ for attr in attributes.getNames():\r
+ if attr == "crown_rotate_step":\r
+ self.rotateEventFactor = float(attributes["crown_rotate_step"])\r
+ elif attr == "animator_rotate_step":\r
+ self.rotateAnimatorValue = float(attributes["animator_rotate_step"])\r
+\r
+ if "display_mode" in attributes.getNames():\r
+ display_mode = attributes["display_mode"]\r
+ if display_mode == "normal":\r
+ self.displayMode = 0\r
+ elif display_mode == "ambient":\r
+ self.displayMode= 1\r
+ elif display_mode == "always":\r
+ self.displayMode= 2\r
+\r
+ def get_bytes(self):\r
+ return bytes(self)\r
+\r
+ def get_size(self):\r
+ return sizeof(self)\r
--- /dev/null
+#!/usr/bin/python\r
+# coding: utf-8\r
+import sys\r
+import struct\r
+import numpy as np\r
+from xml.dom.minidom import parse\r
+from ctypes import *\r
+from common_types import Rect\r
+\r
+class DialLabel(Structure):\r
+ _fields_ = [\r
+ ('breakMode', c_ubyte),\r
+ ('align', c_ubyte),\r
+ ('fontSize', c_ubyte),\r
+ ('isPeriodic', c_bool),\r
+ ('rect', Rect),\r
+ ('color', c_uint),\r
+ ('fontName', c_char * 64),\r
+ ('text', c_char * 64),\r
+ ('bindData', c_short),\r
+ ('displayMode', c_ubyte),\r
+ ('isAmbientPeriodic', c_bool)\r
+ ]\r
+\r
+ def __init__(self):\r
+ self.period = 0\r
+ self.isPeriodic = False\r
+ self.displayMode = 0\r
+ self.isAmbientPeriodic = False\r
+\r
+ def parse_attributes(self, attributes):\r
+ x,y,w,h = attributes["rect"].split(" ")\r
+ self.rect.x = int(x)\r
+ if self.rect.x < np.iinfo(np.int16).min or self.rect.x > np.iinfo(np.int16).max:\r
+ print("[ERR]:label rect x out of range")\r
+ sys.exit(1)\r
+ self.rect.y = int(y)\r
+ if self.rect.y < np.iinfo(np.int16).min or self.rect.y > np.iinfo(np.int16).max:\r
+ print("[ERR]:label rect y out of range")\r
+ sys.exit(1)\r
+ self.rect.w = int(w)\r
+ if self.rect.w < np.iinfo(np.int16).min or self.rect.w > np.iinfo(np.int16).max:\r
+ print("[ERR]:label rect w out of range")\r
+ sys.exit(1)\r
+ self.rect.h = int(h)\r
+ if self.rect.h < np.iinfo(np.int16).min or self.rect.h > np.iinfo(np.int16).max:\r
+ print("[ERR]:label rect h out of range")\r
+ sys.exit(1)\r
+\r
+ mode = attributes["break_mode"]\r
+ if mode == "adapt":\r
+ self.breakMode = 0\r
+ elif mode == "stretch":\r
+ self.breakMode = 1\r
+ elif mode == "wrap":\r
+ self.breakMode = 2\r
+ elif mode == "ellipsis":\r
+ self.breakMode = 3\r
+ elif mode == "marquee":\r
+ self.breakMode = 4\r
+ elif mode == "clip":\r
+ self.breakMode = 5\r
+ else:\r
+ self.breakMode = 3\r
+ print("[WARNING][label:break_mode]Incorrect input:", mode)\r
+\r
+ alignStr = attributes["align"]\r
+ if alignStr == "bottom":\r
+ self.align = 4\r
+ elif alignStr == "top":\r
+ self.align = 3\r
+ elif alignStr == "center":\r
+ self.align = 2\r
+ elif alignStr == "right":\r
+ self.align = 1\r
+ elif alignStr == "left":\r
+ self.align = 0\r
+ else:\r
+ self.align = 0\r
+ print("[WARNING][label:align]Incorrect input:", alignStr)\r
+\r
+ self.fontSize = int(attributes["font_size"])\r
+ if self.fontSize < 0 or self.fontSize > np.iinfo(np.uint8).max:\r
+ print("[ERR]:label font size out of range")\r
+ sys.exit(1)\r
+\r
+ self.color = int(attributes["color"], 16)\r
+ self.fontName = bytes(attributes["font"], encoding = "utf8")\r
+ self.text = bytes(attributes["text"], encoding = "utf8")\r
+\r
+ for attr in attributes.getNames():\r
+ if attr == "bind_data":\r
+ self.bindData = int(attributes["bind_data"])\r
+ if self.bindData < 0 or self.bindData > np.iinfo(np.int16).max:\r
+ print("[ERR]:label bind data out of range")\r
+ sys.exit(1)\r
+ elif attr == "period":\r
+ period_suppor_value = {1, 10, 30, 60}\r
+ self.period = int(attributes["period"])\r
+ if self.period == 0:\r
+ self.isPeriodic = False\r
+ elif self.period not in period_suppor_value:\r
+ self.period = 0\r
+ print("[WARNING]:label image period value not support, using defalut value 0")\r
+ else:\r
+ self.isPeriodic = True\r
+\r
+ if "display_mode" in attributes.getNames():\r
+ display_mode = attributes["display_mode"]\r
+ if display_mode == "normal":\r
+ self.displayMode = 0\r
+ elif display_mode == "ambient":\r
+ self.displayMode= 1\r
+ elif display_mode == "always":\r
+ self.displayMode= 2\r
+ if self.displayMode != 0 :\r
+ if "ambient_periodic" in attributes.getNames():\r
+ if attributes["ambient_periodic"] == "true":\r
+ self.isAmbientPeriodic = True\r
+\r
+ if self.isPeriodic != 0 and self.bindData == 0:\r
+ print("[ERR]:[bind_data] is not set, [period] cannot be set")\r
+ sys.exit(1)\r
+\r
+ def get_bytes(self):\r
+ return bytes(self)\r
+\r
+ def get_size(self):\r
+ return sizeof(self)
\ No newline at end of file
--- /dev/null
+#!/usr/bin/python\r
+# coding: utf-8\r
+import sys\r
+import struct\r
+import numpy as np\r
+from xml.dom.minidom import parse\r
+from ctypes import *\r
+from common_types import Point\r
+import img_convert\r
+\r
+class DialOptionImg(Structure):\r
+ _fields_ = [\r
+ ('pos', Point),\r
+ ('bindData', c_short),\r
+ ('isPeriodic', c_bool),\r
+ ('count', c_ubyte),\r
+ ('displayMode', c_ubyte),\r
+ ('isAmbientPeriodic', c_bool)\r
+ ]\r
+\r
+ def __init__(self):\r
+ self.imgId = []\r
+ self.period = 0\r
+ self.isPeriodic = False\r
+ self.displayMode = 0\r
+ self.isAmbientPeriodic = False\r
+\r
+ def parse_attributes(self, attributes):\r
+ input_pos_x,input_pos_y = attributes["position"].split(" ")\r
+ self.pos.x = int(input_pos_x)\r
+ if self.pos.x < np.iinfo(np.int16).min or self.pos.x > np.iinfo(np.int16).max:\r
+ print("[ERR]:option image pos x out of range")\r
+ sys.exit(1)\r
+\r
+ self.pos.y = int(input_pos_y)\r
+ if self.pos.y < np.iinfo(np.int16).min or self.pos.y > np.iinfo(np.int16).max:\r
+ print("[ERR]:option image pos y out of range")\r
+ sys.exit(1)\r
+\r
+ self.bindData = int(attributes["bind_data"])\r
+ if self.bindData < 0 or self.bindData > np.iinfo(np.int16).max:\r
+ print("[ERR]:option image bind data out of range")\r
+ sys.exit(1)\r
+\r
+ imgNames = attributes["img_names"].split(",")\r
+\r
+ if "display_mode" in attributes.getNames():\r
+ display_mode = attributes["display_mode"]\r
+ if display_mode == "normal":\r
+ self.displayMode = 0\r
+ elif display_mode == "ambient":\r
+ self.displayMode= 1\r
+ elif display_mode == "always":\r
+ self.displayMode= 2\r
+ if self.displayMode != 0:\r
+ if "ambient_periodic" in attributes.getNames():\r
+ if attributes["ambient_periodic"] == "true":\r
+ self.isAmbientPeriodic = True\r
+\r
+ self.count = len(imgNames)\r
+ for img in imgNames:\r
+ imgId = img_convert.instance.convert_img(img)\r
+ self.imgId.append(imgId)\r
+\r
+ if "period" in attributes.getNames():\r
+ period_suppor_value = {1, 10, 30, 60}\r
+ self.period = int(attributes["period"])\r
+ if self.period == 0:\r
+ self.isPeriodic = False\r
+ elif self.period not in period_suppor_value:\r
+ self.period = 0\r
+ print("[WARNING]:option image period value not support, using defalut value 0")\r
+ else:\r
+ self.isPeriodic = True\r
+\r
+ def get_bytes(self):\r
+ ret = bytes(self)\r
+ for index in range(self.count):\r
+ ret += struct.pack('@H', self.imgId[index])\r
+ return ret\r
+\r
+ def get_size(self):\r
+ return sizeof(self) + sizeof(c_ushort) * self.count
\ No newline at end of file
--- /dev/null
+#!/usr/bin/python\r
+# coding: utf-8\r
+import sys\r
+import struct\r
+import numpy as np\r
+from xml.dom.minidom import parse\r
+from ctypes import *\r
+from common_types import Point\r
+import img_convert\r
+\r
+class DialRotateImg(Structure):\r
+ _fields_ = [\r
+ ('pos', Point),\r
+ ('center', Point),\r
+ ('rotateStart', c_short),\r
+ ('rotaeteEnd', c_short),\r
+ ('imgId', c_ushort),\r
+ ('bindData', c_short),\r
+ ('isPeriodic', c_bool),\r
+ ('displayMode', c_ubyte),\r
+ ('isAmbientPeriodic', c_bool)\r
+ ]\r
+\r
+ def __init__(self):\r
+ self.period = 0\r
+ self.isPeriodic = False\r
+ self.displayMode = 0\r
+ self.isAmbientPeriodic = False\r
+\r
+ def parse_attributes(self, attributes):\r
+ input_pos_x,input_pos_y = attributes["position"].split(" ")\r
+ self.pos.x = int(input_pos_x)\r
+ if self.pos.x < np.iinfo(np.int16).min or self.pos.x > np.iinfo(np.int16).max:\r
+ print("[ERR]:rotate image pos x out of range")\r
+ sys.exit(1)\r
+\r
+ self.pos.y = int(input_pos_y)\r
+ if self.pos.y < np.iinfo(np.int16).min or self.pos.y > np.iinfo(np.int16).max:\r
+ print("[ERR]:rotate image pos y out of range")\r
+ sys.exit(1)\r
+\r
+ x,y = attributes["rotate_center"].split(" ")\r
+ self.center.x = round(float(x))\r
+ self.center.y = round(float(y))\r
+\r
+ self.rotateStart = int(attributes["rotate_start"])\r
+ if self.rotateStart < 0.0 or self.rotateStart > 360.0 :\r
+ print("[ERR]:rotate image start angle out of range, [0, 360]")\r
+ sys.exit(1)\r
+\r
+ self.rotaeteEnd = int(attributes["rotate_end"])\r
+ if self.rotaeteEnd < 0.0 or self.rotaeteEnd > 360.0 :\r
+ print("[ERR]:rotate image end angle out of range, [0, 360]")\r
+ sys.exit(1)\r
+\r
+ self.bindData = int(attributes["bind_data"])\r
+ if self.bindData < 0 or self.bindData > np.iinfo(np.int16).max:\r
+ print("[ERR]:rotate image bind data out of range")\r
+ sys.exit(1)\r
+\r
+ self.imgId = img_convert.instance.convert_img(attributes["img_name"])\r
+ if "period" in attributes.getNames():\r
+ period_suppor_value = {1, 10, 30, 60}\r
+ self.period = int(attributes["period"])\r
+ if self.period == 0:\r
+ self.isPeriodic = False\r
+ elif self.period not in period_suppor_value:\r
+ self.period = 0\r
+ print("[WARNING]:rotate image period value not support, using defalut value 0")\r
+ else:\r
+ self.isPeriodic = True\r
+\r
+ if "display_mode" in attributes.getNames():\r
+ display_mode = attributes["display_mode"]\r
+ if display_mode == "normal":\r
+ self.displayMode = 0\r
+ elif display_mode == "ambient":\r
+ self.displayMode = 1\r
+ elif display_mode == "always":\r
+ self.displayMode = 2\r
+ if self.displayMode != 0:\r
+ if "ambient_periodic" in attributes.getNames():\r
+ if attributes["ambient_periodic"] == "true":\r
+ self.isAmbientPeriodic = True\r
+\r
+ def get_bytes(self):\r
+ return bytes(self)\r
+\r
+ def get_size(self):\r
+ return sizeof(self)
\ No newline at end of file
--- /dev/null
+#!/usr/bin/python\r
+# coding: utf-8\r
+import sys\r
+import struct\r
+import numpy as np\r
+from xml.dom.minidom import parse\r
+from ctypes import *\r
+from common_types import Point\r
+import img_convert\r
+\r
+class DialSequenceImg(Structure):\r
+ _fields_ = [\r
+ ('pos', Point),\r
+ ('interval', c_ushort),\r
+ ('repeat', c_bool),\r
+ ('imgNum', c_ubyte),\r
+ ('displayMode', c_ubyte)\r
+ ]\r
+\r
+ def __init__(self):\r
+ self.imgId = []\r
+ self.period = 0\r
+ self.displayMode = 0\r
+\r
+ def parse_attributes(self, attributes):\r
+ x,y = attributes["position"].split(" ")\r
+ self.pos.x = int(x)\r
+ if self.pos.x < np.iinfo(np.int16).min or self.pos.x > np.iinfo(np.int16).max :\r
+ print("[ERR]:sequence image pos x out of range")\r
+ sys.exit(1)\r
+\r
+ self.pos.y = int(y)\r
+ if self.pos.y < np.iinfo(np.int16).min or self.pos.y > np.iinfo(np.int16).max :\r
+ print("[ERR]:sequence image pos y out of range")\r
+ sys.exit(1)\r
+\r
+ if attributes["repeat"].lower() == "true" :\r
+ self.repeat = True\r
+ elif attributes["repeat"].lower() == "false" :\r
+ self.repeat = False\r
+ else:\r
+ print("[ERR]:sequence image repeat only 'True' or 'False'")\r
+ sys.exit(1)\r
+\r
+ interval = int(attributes["interval"])\r
+ if interval < 0 or interval > np.iinfo(np.int16).max :\r
+ print("[ERR]: sequence image interval out of range")\r
+ sys.exit(1)\r
+ else:\r
+ self.interval = interval\r
+\r
+ imgNames = attributes["img_names"].split(",")\r
+ self.imgNum = len(imgNames)\r
+ for img in imgNames:\r
+ imgId = img_convert.instance.convert_img(img)\r
+ self.imgId.append(imgId)\r
+\r
+ if "display_mode" in attributes.getNames():\r
+ display_mode = attributes["display_mode"]\r
+ if display_mode == "normal":\r
+ self.displayMode = 0\r
+ elif display_mode == "ambient":\r
+ self.displayMode= 1\r
+ elif display_mode == "always":\r
+ self.displayMode= 2\r
+\r
+ def get_bytes(self):\r
+ ret = bytes(self)\r
+ for index in range(self.imgNum):\r
+ ret += struct.pack('@H', self.imgId[index])\r
+ return ret\r
+\r
+ def get_size(self):\r
+ return sizeof(self) + sizeof(c_ushort) * self.imgNum
\ No newline at end of file
--- /dev/null
+#!/usr/bin/python\r
+# coding: utf-8\r
+import sys\r
+import struct\r
+import numpy as np\r
+from xml.dom.minidom import parse\r
+from ctypes import *\r
+from common_types import Point\r
+import img_convert\r
+\r
+class DialStaticImg(Structure):\r
+ _fields_ = [\r
+ ('pos', Point),\r
+ ('center', Point),\r
+ ('rotate', c_float),\r
+ ('imgId', c_ushort),\r
+ ('displayMode', c_ubyte),\r
+ ]\r
+\r
+ def __init__(self):\r
+ self.imgId = 0\r
+ self.center.x = 0\r
+ self.center.y = 0\r
+ self.rotate = 0.0\r
+ self.period = 0\r
+ self.displayMode = 0\r
+\r
+ def parse_attributes(self, attributes):\r
+ input_pos_x, input_pos_y = attributes["position"].split(" ")\r
+ self.pos.x = int(input_pos_x)\r
+ if self.pos.x < np.iinfo(np.int16).min or self.pos.x > np.iinfo(np.int16).max:\r
+ print("[ERR]:static image pos x out of range")\r
+ sys.exit(1)\r
+\r
+ self.pos.y = int(input_pos_y)\r
+ if self.pos.y < np.iinfo(np.int16).min or self.pos.y > np.iinfo(np.int16).max:\r
+ print("[ERR]:static image pos y out of range")\r
+ sys.exit(1)\r
+\r
+ self.imgId = img_convert.instance.convert_img(attributes["img_name"])\r
+\r
+ for attr in attributes.getNames():\r
+ if attr == "center":\r
+ input_center_x,input_center_y = attributes["center"].split(" ")\r
+ self.center.x = int(input_center_x)\r
+ if self.center.x < np.iinfo(np.int16).min or self.center.x > np.iinfo(np.int16).max:\r
+ print("[ERR]:static image center x out of range")\r
+ sys.exit(1)\r
+\r
+ self.center.y = int(input_center_y)\r
+ if self.center.y < np.iinfo(np.int16).min or self.center.y > np.iinfo(np.int16).max:\r
+ print("[ERR]:static image center y out of range")\r
+ sys.exit(1)\r
+ elif attr == "rotate":\r
+ rotate = float(attributes["rotate"])\r
+ if rotate < 0.0 or rotate > 360.0 :\r
+ print("[ERR]:static image rotate out of range, [0, 360]")\r
+ sys.exit(1)\r
+ self.rotate = rotate\r
+\r
+ if "display_mode" in attributes.getNames():\r
+ display_mode = attributes["display_mode"]\r
+ if display_mode == "normal":\r
+ self.displayMode = 0\r
+ elif display_mode == "ambient":\r
+ self.displayMode = 1\r
+ elif display_mode == "always":\r
+ self.displayMode = 2\r
+\r
+ def get_bytes(self):\r
+ return bytes(self)\r
+\r
+ def get_size(self):\r
+ return sizeof(self)\r
--- /dev/null
+#!/usr/bin/python\r
+# coding: utf-8\r
+import sys\r
+import struct\r
+import numpy as np\r
+from xml.dom.minidom import parse\r
+from ctypes import *\r
+from common_types import Rect\r
+import video_convert\r
+import img_convert\r
+\r
+class DialVideo(Structure):\r
+ _fields_ = [\r
+ ('rect', Rect),\r
+ ('offset', c_uint),\r
+ ('colorKey', c_uint),\r
+ ('imgId', c_uint),\r
+ ('displayMode', c_ubyte)\r
+ ]\r
+\r
+ def __init__(self):\r
+ self.period = 0\r
+ self.displayMode = 0\r
+\r
+ def parse_attributes(self, attributes):\r
+ x,y,w,h = attributes["rect"].split(" ")\r
+ self.rect.x = int(x)\r
+ if self.rect.x < np.iinfo(np.int16).min or self.rect.x > np.iinfo(np.int16).max:\r
+ print("[ERR]:video rect x out of range")\r
+ sys.exit(1)\r
+ self.rect.y = int(y)\r
+ if self.rect.y < np.iinfo(np.int16).min or self.rect.y > np.iinfo(np.int16).max:\r
+ print("[ERR]:video rect y out of range")\r
+ sys.exit(1)\r
+ self.rect.w = int(w)\r
+ if self.rect.w < np.iinfo(np.int16).min or self.rect.w > np.iinfo(np.int16).max:\r
+ print("[ERR]:video rect w out of range")\r
+ sys.exit(1)\r
+ self.rect.h = int(h)\r
+ if self.rect.h < np.iinfo(np.int16).min or self.rect.h > np.iinfo(np.int16).max:\r
+ print("[ERR]:video rect h out of range")\r
+ sys.exit(1)\r
+\r
+ self.colorKey = int(attributes["color_key"], 16)\r
+ self.offset = video_convert.instance.convert_video(attributes["source"])\r
+ self.imgId = img_convert.instance.convert_img(attributes["preview_frame"])\r
+\r
+ if "display_mode" in attributes.getNames():\r
+ display_mode = attributes["display_mode"]\r
+ if display_mode == "normal":\r
+ self.displayMode = 0\r
+ elif display_mode == "ambient":\r
+ self.displayMode= 1\r
+ elif display_mode == "always":\r
+ self.displayMode= 2\r
+\r
+ def get_bytes(self):\r
+ return bytes(self)\r
+\r
+ def get_size(self):\r
+ return sizeof(self)
\ No newline at end of file
--- /dev/null
+import base64\r
+from PIL import Image\r
+from io import BytesIO\r
+import cv2\r
+import ctypes\r
+from ctypes import *\r
+from PIL import Image\r
+\r
+import os\r
+import sys\r
+import struct\r
+import time\r
+import platform\r
+import numpy as np\r
+import pickle as p\r
+import requests\r
+import matplotlib.pyplot as pyplot\r
+\r
+global dll\r
+if platform.system().lower() == 'windows':\r
+ dll = ctypes.CDLL(r".\dll\x64\release_cs\ICE_V5R1_BLOCK_HTC.dll")\r
+elif platform.system().lower() == 'linux':\r
+ dll = ctypes.CDLL(sys.path[0] + r"/dll/linux_cs/libcodec.so")\r
+\r
+class Header(ctypes.Structure):\r
+ _fields_ = [\r
+ ("width", c_uint),\r
+ ("height", c_uint),\r
+ ("stride", c_uint),\r
+ ("pixel_format", c_uint),\r
+ ("tile_width", c_uint),\r
+ ("mode_alpha", c_uint),\r
+ ("mode_rgb", c_uint)\r
+ ]\r
+\r
+class BsData(ctypes.Structure):\r
+ _fields_ = [\r
+ ("bs_data", POINTER(c_ubyte)),\r
+ ("data_size", c_uint),\r
+ ("cmp_ratio", c_uint),\r
+ ("is_valid", c_uint),\r
+ ("subjective_review", c_uint),\r
+ ("para", Header)\r
+ ]\r
+\r
+class AutoCmpOutput(ctypes.Structure):\r
+ _fields_ = [\r
+ ("cmp_bs0", POINTER(BsData)),\r
+ ("cmp_bs1", POINTER(BsData)),\r
+ ("cmp_bs2", POINTER(BsData)),\r
+ ("cmp_bs3", POINTER(BsData)),\r
+ ("auto_cmp_mode", c_uint),\r
+ ("valid_bs_num", c_uint)\r
+ ]\r
+\r
+class CmpInput(ctypes.Structure):\r
+ _fields_ = [\r
+ ("width", c_uint),\r
+ ("height", c_uint),\r
+ ("stride", c_uint),\r
+ ("pixel_format", c_uint),\r
+ ("tile_width", c_uint),\r
+ ("mode_alpha", c_uint),\r
+ ("mode_rgb", c_uint),\r
+ ("red_channel", POINTER(c_ubyte)),\r
+ ("green_channel", POINTER(c_ubyte)),\r
+ ("blue_channel", POINTER(c_ubyte)),\r
+ ("alpha_channel", POINTER(c_ubyte))\r
+ ]\r
+\r
+class AutoCmpInput(ctypes.Structure):\r
+ _fields_ =[\r
+ ("auto_cmp_mode", c_uint),\r
+ ("high_quality_mode", c_uint),\r
+ ("high_cmp_ratio_mode", c_uint),\r
+ ("cmp_in", POINTER(CmpInput))\r
+ ]\r
+\r
+class BinHeader(ctypes.Structure):\r
+ _fields_ = [\r
+ ("dirId", c_uint),\r
+ ("count", c_uint)\r
+ ]\r
+\r
+class SeekInfo(ctypes.Structure):\r
+ _fields_ = [\r
+ ("offset", c_uint),\r
+ ("size", c_uint)\r
+ ]\r
+\r
+class ImageHeader(ctypes.Structure):\r
+ _fields_ = [\r
+ ("colorMode", c_uint, 8),\r
+ ("version", c_uint, 4),\r
+ ("compressMode", c_uint, 4),\r
+ ("reserved", c_uint, 16),\r
+ ("width", c_ushort),\r
+ ("height", c_ushort)\r
+ ]\r
+\r
+class ImageConverTool():\r
+ binHeader = BinHeader()\r
+ binHeader.dirId = 0xfef\r
+ seekInfo = []\r
+ imageHeader = []\r
+ imageData = []\r
+ imageNum = 0\r
+ isConvertedFile = []\r
+ tile_width_support = {4, 6, 8, 16}\r
+\r
+ def __init__(self):\r
+ self.markCurOffset = 0\r
+ self.width = 0\r
+ self.height = 0\r
+ self.file_alpha = False\r
+ self.cmp_mode = "HFBC"\r
+ self.color_fmt = ' '\r
+ self.align = 1\r
+ self.tile_width = 6\r
+ self.mode_alpha = 1\r
+ self.mode_rgb = 1\r
+ self.auto_cmp_mode = 0\r
+ self.high_quality_mode = 0\r
+ self.high_cmp_ratio_mode = 0\r
+ self.version = 1\r
+\r
+ def set_tile_width(self, tile_width):\r
+ if tile_width not in self.tile_width_support:\r
+ print("[ERR]:The tile_width:{tile_width} value is not supported.")\r
+ sys.exit(1)\r
+\r
+ self.tile_width = tile_width\r
+\r
+ def _convert(self):\r
+ width, height = self.image.size\r
+ self.width = width\r
+ self.height = height\r
+ self.stride_pixel = (self.width + self.align - 1) // self.align * self.align\r
+ if len(self.image.split()) > 3:\r
+ self.file_alpha = True\r
+ else:\r
+ self.file_alpha = False\r
+\r
+ # initialize CmpInput\r
+ cmp_input = CmpInput()\r
+ self._get_cmp_input(cmp_input)\r
+ auto_cmp_input = AutoCmpInput()\r
+ self._get_auto_cmp_input(auto_cmp_input, cmp_input)\r
+\r
+ # call GetBufferSize to get buffer size\r
+ # initialize CmpOutput\r
+ auto_cmp_output = AutoCmpOutput()\r
+\r
+ cmp_bs0 = BsData()\r
+ buf_size0 = dll.ice_v5r1_block_get_buffer_size(byref(cmp_input)) # 压缩后输出数据的大小\r
+ cmp_bs0.bs_data = (c_ubyte * buf_size0)()\r
+ auto_cmp_output.cmp_bs0 = ctypes.cast(pointer(cmp_bs0), POINTER(BsData))\r
+ ret = dll.ice_v5r1_block_htc_auto_cmp(byref(auto_cmp_input), byref(auto_cmp_output)) # 对输入数据进行压缩返回值是函数正常运行标志位\r
+\r
+ # add imageinfo to list\r
+ self.binHeader.count += 1\r
+\r
+ imageInfo = ImageHeader()\r
+ imageInfo.width = self.width\r
+ imageInfo.height = self.height\r
+ imageInfo.colorMode = self._get_color_mode()\r
+ imageInfo.version = 1\r
+ imageInfo.compressMode = 4\r
+ imageInfo.reserved = 0\r
+ seekInfo = SeekInfo()\r
+ seekInfo.offset = self.markCurOffset\r
+ seekInfo.size = sizeof(imageInfo) + cmp_bs0.data_size\r
+ self.markCurOffset += seekInfo.size\r
+ self.seekInfo.append(seekInfo)\r
+ self.imageHeader.append(imageInfo)\r
+ self.imageData.append(cmp_bs0)\r
+ self.imageNum += 1\r
+ return self.imageNum\r
+\r
+ def _check_path(self, path):\r
+ if not os.path.exists(path):\r
+ print("[ERROR]:", path, "is not exist")\r
+ return False\r
+ else:\r
+ if (not path[-3:].lower() == "png") and (not path[-3:].lower() == "jpg") and (not path[-3:].lower() == "bmp"):\r
+ print("[ERROR]:", path, "is not jpg or png or bmp format image")\r
+ return False\r
+ return True\r
+\r
+ def convert_img(self, path):\r
+ if path in self.isConvertedFile:\r
+ return self.isConvertedFile.index(path) + 1\r
+\r
+ if not self._check_path(path):\r
+ sys.exit(1)\r
+\r
+ self.image = Image.open(path)\r
+ if self.image.mode == 'RGBA':\r
+ self.color_fmt = 'ARGB8888'\r
+ elif self.image.mode == 'RGB':\r
+ self.color_fmt = 'RGB888'\r
+ self.isConvertedFile.append(path)\r
+ return self._convert()\r
+\r
+ def _get_cmp_px_format(self):\r
+ if self.color_fmt == 'RGB565':\r
+ return 2\r
+ elif self.color_fmt == 'RGB888':\r
+ return 0\r
+ elif self.color_fmt == 'ARGB8888':\r
+ return 1\r
+\r
+ def _get_color_mode(self):\r
+ if self.color_fmt == 'RGB565':\r
+ return 2\r
+ elif self.color_fmt == 'RGB888':\r
+ return 1\r
+ elif self.color_fmt == 'ARGB8888':\r
+ return 0\r
+\r
+ def _get_auto_cmp_input(self, auto_cmp_input, cmp_input):\r
+ auto_cmp_input.auto_cmp_mode = self.auto_cmp_mode\r
+ auto_cmp_input.high_quality_mode = self.high_quality_mode\r
+ auto_cmp_input.high_cmp_ratio_mode = self.high_cmp_ratio_mode\r
+ auto_cmp_input.cmp_in = ctypes.cast(pointer(cmp_input), POINTER(CmpInput))\r
+\r
+ def _get_cmp_input(self, cmp_input):\r
+ cmp_input.width = self.width\r
+ cmp_input.height = self.height\r
+ cmp_input.stride = self.width\r
+ cmp_input.tile_width = self.tile_width\r
+ cmp_input.mode_alpha = self.mode_alpha\r
+ cmp_input.mode_rgb = self.mode_rgb\r
+ cmp_input.pixel_format = self._get_cmp_px_format()\r
+ size = self.width * self.height\r
+ red = (c_ubyte * size)()\r
+ green = (c_ubyte * size)()\r
+ blue = (c_ubyte * size)()\r
+ alpha = (c_ubyte * size)()\r
+\r
+ for row in range(self.height):\r
+ for col in range(self.width):\r
+ position = row * self.width + col\r
+ red[position] = self.image.getdata()[position][0]\r
+ green[position] = self.image.getdata()[position][1]\r
+ blue[position] = self.image.getdata()[position][2]\r
+ if self.file_alpha == False:\r
+ alpha[position] = 0xFF\r
+ else:\r
+ alpha[position] = self.image.getdata()[position][3]\r
+ cmp_input.red_channel = red\r
+ cmp_input.green_channel = green\r
+ cmp_input.blue_channel = blue\r
+ cmp_input.alpha_channel = alpha\r
+\r
+ def write_data_to_bin(self, fb):\r
+ fb.write(bytes(self.binHeader))\r
+ for seek in self.seekInfo:\r
+ fb.write(bytes(seek))\r
+\r
+ for index in range(0, self.imageNum):\r
+ bt = bytearray()\r
+ color_fmt = self.imageHeader[index].colorMode\r
+ header = color_fmt + (self.imageHeader[index].width << 32) + \\r
+ (self.imageHeader[index].height << 48) + (self.imageHeader[index].version << 8)\r
+ header_bin = struct.pack("<Q", header)\r
+\r
+ if (self.cmp_mode == "HFBC"):\r
+ header = header + (4 << 12)\r
+ elif (self.cmp_mode == "HFBC_ABYPASS"):\r
+ header = header + (5 << 12)\r
+\r
+ header_bin = struct.pack("<Q", header)\r
+ bt += header_bin\r
+ for i in range(self.imageData[index].data_size):\r
+ bt += struct.pack("B", self.imageData[index].bs_data[i])\r
+ fb.writelines([bt])\r
+\r
+ def get_size(self):\r
+ ret = sizeof(self.binHeader)\r
+ ret += len(self.seekInfo) * sizeof(SeekInfo)\r
+ for index in range(0, self.imageNum):\r
+ bt = bytearray()\r
+ color_fmt = self._get_cmp_px_format()\r
+ header = color_fmt + (self.imageHeader[index].width << 32) + \\r
+ (self.imageHeader[index].height << 48) + (self.imageHeader[index].version << 8)\r
+ header_bin = struct.pack("<Q", header)\r
+\r
+ if (self.cmp_mode == "HFBC"):\r
+ header = header + (4 << 12)\r
+ elif (self.cmp_mode == "HFBC_ABYPASS"):\r
+ header = header + (5 << 12)\r
+\r
+ header_bin = struct.pack("<Q", header)\r
+ bt += header_bin\r
+ for i in range(self.imageData[index].data_size):\r
+ bt += struct.pack("B", self.imageData[index].bs_data[i])\r
+ ret += len(bt)\r
+ return ret\r
+\r
+instance = ImageConverTool()\r
--- /dev/null
+<dial ambient_period="10" title="clock" description="main clock" size="454 454" version="2.0" preview_img="./instance/analogue_dial/preview_img.JPG">\r
+ <static_img id="back_ground" position="0 0" img_name="./instance/analogue_dial/MAIN_FACE_IMAGE.png"></static_img>\r
+ <option_img position="207 127" img_names="./instance/analogue_dial/week/MONDAY_IMAGE_PATH.png,./instance/analogue_dial/week/TUESDAY_IMAGE_PATH.png,./instance/analogue_dial/week/WEDNESDAY_IMAGE_PATH.png,./instance/analogue_dial/week/THURSDAY_IMAGE_PATH.png,./instance/analogue_dial/week/FIRDAY_IMAGE_PATH.png,./instance/analogue_dial/week/SATURDAY_IMAGE_PATH.png,./instance/analogue_dial/week/SUNDAY_IMAGE_PATH.png" bind_data="17" period="10"></option_img>\r
+ <label display_mode="normal" id="step_label" color="0xFFFFFFFF" font="HarmonyOS_Sans_SC_Regular.ttf" break_mode="ellipsis" rect="100 230 75 35" text="%5.0f" font_size="25" align="center" bind_data="1" period="10"></label>\r
+ <static_img id="heart_rate" position="156 260" img_name="./instance/analogue_dial/HEARTRATE_IMAGE_PATH.png"></static_img>\r
+ <label display_mode="ambient" ambient_periodic="true" id="heart_label" color="0xFFFFFFFF" font="HarmonyOS_Sans_SC_Regular.ttf" break_mode="ellipsis" rect="198 330 60 35" text="%3.0f" font_size="25" align="center" bind_data="2" period="10"></label>\r
+ <static_img id="progress" position="53 54" img_name="./instance/analogue_dial/PROGRESS_IMAGE_PATH.png"></static_img>\r
+ <label id="battery_label" color="0xFFFFFFFF" font="HarmonyOS_Sans_SC_Regular.ttf" break_mode="ellipsis" rect="315 230 60 35" text="%2.0f%%" font_size="25" align="center" bind_data="8" period="10"></label>\r
+ <rotate_img id="hour" position="202 16" rotate_center="25.0 211.0" rotate_start="0" rotate_end="360" img_name="./instance/analogue_dial/HOURHAND.png" bind_data="9" period="10"></rotate_img>\r
+ <static_img id="hour_circle" position="202 202" img_name="./instance/analogue_dial/BIGCIRCLE_IMAGE_PATH.png"></static_img>\r
+ <rotate_img id="minute" position="202 16" rotate_center="25.0 211.0" rotate_start="0" rotate_end="360" img_name="./instance/analogue_dial/MINUTEHAND.png" bind_data="10" period="10"></rotate_img>\r
+ <static_img display_mode="ambient" id="minute_circle" position="202 202" img_name="./instance/analogue_dial/MEDCIRCLE_IMAGE_PATH.png"></static_img>\r
+ <rotate_img display_mode="always" ambient_periodic="true" id="second" position="202 16" rotate_center="25.0 211.0" rotate_start="0" rotate_end="360" img_name="./instance/analogue_dial/SECONDHAND.png" bind_data="12" period="60"></rotate_img>\r
+ <static_img id="second_circle" position="215 213" img_name="./instance/analogue_dial/SMALLCIRCLE_IMAGE_PATH.png"></static_img>\r
+</dial>
\ No newline at end of file
--- /dev/null
+<dial title="kaleidoscope" description="kaleidoscope dial" size="454 454" version="1.0" preview_img="./instance/kaleidoscope_dial/preview_img.PNG">\r
+ <kaleidoscope id="kale" img_name="./instance/kaleidoscope_dial/rabbit454.png" crown_rotate_step="0.2" animator_rotate_step="0.1"></kaleidoscope>\r
+ <rotate_img id="hour" position="202 16" rotate_center="25.0 211.0" rotate_start="0" rotate_end="360" img_name="./instance/kaleidoscope_dial/HOURHAND.png" bind_data="9" period="10"></rotate_img>\r
+ <static_img id="hour_circle" position="202 202" img_name="./instance/kaleidoscope_dial/BIGCIRCLE_IMAGE_PATH.png"></static_img>\r
+ <rotate_img id="minute" position="202 16" rotate_center="25.0 211.0" rotate_start="0" rotate_end="360" img_name="./instance/kaleidoscope_dial/MINUTEHAND.png" bind_data="10" period="10"></rotate_img>\r
+ <static_img id="minute_circle" position="202 202" img_name="./instance/kaleidoscope_dial/MEDCIRCLE_IMAGE_PATH.png"></static_img>\r
+ <rotate_img id="second" position="202 16" rotate_center="25.0 211.0" rotate_start="0" rotate_end="360" img_name="./instance/kaleidoscope_dial/SECONDHAND.png" bind_data="12" period="60"></rotate_img>\r
+ <static_img id="second_circle" position="215 213" img_name="./instance/kaleidoscope_dial/SMALLCIRCLE_IMAGE_PATH.png"></static_img>\r
+</dial>
\ No newline at end of file
--- /dev/null
+#!/usr/bin/python\r
+# coding: utf-8\r
+# 1\ 解析命令 python main.py -d [DIR] -o [OUT_DIR]\r
+# 2\ 循环执行svg解析写入\r
+import sys\r
+import os\r
+import argparse\r
+from converter import DialConvertTool\r
+\r
+def GetParameters():\r
+ parser = argparse.ArgumentParser()\r
+\r
+ parser.add_argument('-file', '-f', type=str, default='', required=False,\r
+ help='Specifies the path of the offline watch face XML file to be converted.')\r
+\r
+ parser.add_argument('-dir', '-d', type=str, default='', required=False,\r
+ help='Specifies the path of the folder to be converted. Convert all .xml files in the folder according to the specified path.')\r
+\r
+ parser.add_argument('-output', type=str, default=os.getcwd() + "/out", required=False,\r
+ help='output dir')\r
+\r
+ config = parser.parse_args()\r
+ return config\r
+\r
+if __name__ == "__main__":\r
+ userInput = GetParameters()\r
+ outputPath = userInput.output\r
+ inputFile = userInput.file\r
+ inputDir = userInput.dir\r
+ # Create an output folder.\r
+ print("output dir : " + outputPath)\r
+ if not os.path.exists(outputPath):\r
+ os.mkdir(outputPath)\r
+\r
+ if not os.path.isdir(inputFile) and inputFile[-3:].lower() == "xml":\r
+ print("input file : " + inputFile)\r
+ converter = DialConvertTool()\r
+ converter.convert_xml_to_output(inputFile, outputPath)\r
+\r
+ print("inputdir", inputDir)\r
+ files = os.listdir(inputDir)\r
+ print("input dir : " + inputDir)\r
+ for file in files:\r
+ if not os.path.isdir(file) and file[-3:].lower() == "xml":\r
+ converter = DialConvertTool()\r
+ converter.convert_xml_to_output(inputDir + "/" + file, outputPath)
\ No newline at end of file
--- /dev/null
+#!/usr/bin/python\r
+# coding: utf-8\r
+import sys\r
+import struct\r
+import ctypes\r
+from ctypes import *\r
+\r
+class VideoConvertTool:\r
+ def __init__(self):\r
+ self.videoNum = 0\r
+ self.videoName = []\r
+ self.videoIndex = []\r
+ self.videoData = bytearray()\r
+\r
+ def convert_video(self, path):\r
+ if path in self.videoName:\r
+ index = self.videoName.index(path)\r
+ return self.videoIndex[index]\r
+ fp = open(path, 'rb')\r
+ data = fp.read()\r
+ fp.close()\r
+ self.videoName.append(path)\r
+ self.videoNum += 1\r
+ ret = len(self.videoData)\r
+ self.videoIndex.append(ret)\r
+ self.videoData += data\r
+ return ret\r
+\r
+ def write_data_to_bin(self, fb):\r
+ fb.write(self.videoData)\r
+\r
+instance = VideoConvertTool()\r
--- /dev/null
+中文名:动态小鹰\r
+英文名:owl clock\r
+标签:数码表盘;\r
<!-- 时间段背景切换(已实现系统端映射逻辑) -->\r
<option_img position="0 0" img_names="./instance/207/BACKGROUND_0_6.png,./instance/207/BACKGROUND_6_12.png,./instance/207/BACKGROUND_12_18.png,./instance/207/BACKGROUND_18_24.png" bind_data="37" period="10"></option_img>\r
\r
- <!-- 数字时间显示 - 小时 -->\r
- <label id="hour_label" color="0xFFFFFFFF" font="HarmonyOS_Sans_SC_Regular.ttf" break_mode="adapt" rect="86 162 200 60" text="%02.f" font_size="120" align="center" bind_data="15" period="10" display_mode="always" ambient_periodic="true"></label>\r
- \r
- <!-- 数字时间显示 - 分钟 -->\r
- <label id="minute_label" color="0xFF666666" font="HarmonyOS_Sans_SC_Regular.ttf" break_mode="adapt" rect="240 162 200 60" text="%02.f" font_size="120" align="center" bind_data="14" period="10" display_mode="always" ambient_periodic="true"></label>\r
- \r
- <!-- 电池显示 -->\r
- <option_img position="173 52" img_names="./instance/207/Battery/Battery_Nomoal.png,./instance/207/Battery/BatteryCharge.png" bind_data="20" period="10"></option_img>\r
- \r
+\r
+ <!-- 月份显示 -->\r
+ <label id="month_label" color="0xFFFFFFFF" font="HarmonyOS_Sans_SC_Regular.ttf" break_mode="adapt" rect="186 120 60 30" text="%02.0f-" font_size="36" align="center" bind_data="18" period="10"></label>\r
+ <!-- 日期显示 -->\r
+ <label id="day_label" color="0xFFFFFFFF" font="HarmonyOS_Sans_SC_Regular.ttf" break_mode="adapt" rect="246 120 60 30" text="%02.0f" font_size="36" align="center" bind_data="16" period="10"></label>\r
+\r
+ <!-- 小时和分钟 -->\r
+ <label id="hour_ten_label" color="0xFFFFFFFF" font="HarmonyOS_Sans_SC_Regular.ttf" break_mode="ellipsis" rect="83 280 300 120" text="%s" font_size="90" align="center" bind_data="20483" period="10"></label>\r
+\r
+ <!-- 电池进度条 -->\r
+ <box_progress id="battery_progress" rect="224 388 30 18" color="0xFFFFFFFF" cap_type="none" direction="left_to_right" background_color="0x00FFFFFF" bind_data="25" period="10"></box_progress>\r
+ <!-- 电池图像 --> \r
+ <option_img position="217 382" img_names="./instance/1052/Battery/Battery.png,./instance/1052/Battery/BatteryCharge.png" bind_data="20" period="10"></option_img>\r
<!-- 电池百分比标签 -->\r
- <label id="battery_label" color="0xFFFFFFFF" font="HarmonyOS_Sans_SC_Regular.ttf" break_mode="adapt" rect="228 52 200 62" text="%s" font_size="26" align="center" bind_data="20485" period="10"></label>\r
+ <!-- <label id="battery_label" color="0xFFFFFFFF" font="HarmonyOS_Sans_SC_Regular.ttf" break_mode="adapt" rect="228 394 200 62" text="%s" font_size="26" align="center" bind_data="20485" period="10"></label> -->\r
+\r
</dial>\r
--- /dev/null
+<dial title="essential_sport" description="精简运动" size="466 466" version="2.0" preview_img="./instance/208/essential_sport.png">\r
+ <static_img id="back_ground" position="0 0" img_name="./instance/208/MAIN_FACE_IMAGE.png"></static_img>\r
+ \r
+ <static_img id="back_ground" position="0 0" img_name="./instance/208/BACKGROUND_6_12.png"></static_img>\r
+ <!-- 时间段背景切换:0-6点、6-12点、12-18点、18-24点 -->\r
+ <!-- 时间段映射:0-5点->0, 6-11点->1, 12-17点->2, 18-23点->3 -->\r
+ <!-- 时间段背景切换(已实现系统端映射逻辑) -->\r
+ <!-- <option_img position="0 0" img_names="./instance/208/BACKGROUND_0_6.png,./instance/208/BACKGROUND_6_12.png,./instance/208/BACKGROUND_12_18.png,./instance/208/BACKGROUND_18_24.png" bind_data="223" period="10"></option_img> -->\r
+\r
+\r
+ <!-- 时针底部背景 -->\r
+ <static_img id="hand_bottom_bg" position="219 219" img_name="./instance/208/HAND_BOTTOM.png"></static_img>\r
+\r
+ <!-- 时针 (11×66) -->\r
+ <rotate_img id="hour" position="228 167" rotate_center="5.0 66.0" rotate_start="0" rotate_end="360" img_name="./instance/208/HOURHAND.png" bind_data="9" period="10"></rotate_img>\r
+ <!-- 分针 (11×130) -->\r
+ <rotate_img id="minute" position="228 103" rotate_center="5.0 130.0" rotate_start="0" rotate_end="360" img_name="./instance/208/MINUTEHAND.png" bind_data="10" period="10"></rotate_img>\r
+ <!-- 秒针 (6×124) -->\r
+ <rotate_img id="second" position="230 128" rotate_center="3.0 105.0" rotate_start="0" rotate_end="360" img_name="./instance/208/SECONDHAND.png" bind_data="12" period="60"></rotate_img>\r
+\r
+ <!-- 时针顶部背景 -->\r
+ <static_img id="hand_top_bg" position="231 228" img_name="./instance/208/HAND_TOP.png"></static_img>\r
+\r
+\r
+</dial>
\ No newline at end of file
--- /dev/null
+LZMA SDK 21.07
+--------------
+
+UNIX/Linux version
+------------------
+To compile C++ version of file->file LZMA encoding, go to directory
+CPP/7zip/Bundles/LzmaCon
+and call make to recompile it:
+ make -f makefile.gcc clean all