mirror of
https://github.com/OpenVGLab/OmniLottie.git
synced 2026-09-17 07:36:27 +00:00
143 lines
4.8 KiB
Python
143 lines
4.8 KiB
Python
from xml.dom import minidom
|
|
import copy
|
|
from uuid import uuid4
|
|
|
|
from .utils import *
|
|
from lottie.parsers.sif.sif.core import ObjectRegistry
|
|
|
|
|
|
class XmlDescriptor:
|
|
def __init__(self, name):
|
|
self.name = name
|
|
self.att_name = name.replace("-", "_").replace("[", "_").replace("]", "").replace(".", "_")
|
|
|
|
def to_xml(self, obj, parent: minidom.Element, dom: minidom.Document):
|
|
raise NotImplementedError
|
|
|
|
def from_xml(self, obj, parent: minidom.Element, registry: ObjectRegistry):
|
|
raise NotImplementedError
|
|
|
|
def from_python(self, value):
|
|
raise NotImplementedError
|
|
|
|
def initialize_object(self, dict, obj):
|
|
if self.att_name in dict:
|
|
setattr(obj, self.att_name, self.from_python(dict[self.att_name]))
|
|
else:
|
|
setattr(obj, self.att_name, self.default())
|
|
|
|
def clean(self, value):
|
|
return self.from_python(value)
|
|
|
|
def default(self):
|
|
return None
|
|
|
|
def __repr__(self):
|
|
return "%s(%r)" % (self.__class__.__name__, self.name)
|
|
|
|
|
|
class TypedXmlDescriptor(XmlDescriptor):
|
|
def __init__(self, name, type=str, default_value=None, att_name=None):
|
|
super().__init__(name)
|
|
self.type = type
|
|
self.default_value = default_value
|
|
if att_name is not None:
|
|
self.att_name = att_name
|
|
|
|
def from_python(self, value):
|
|
if value is None and self.default_value is None:
|
|
return None
|
|
if not value_isinstance(value, self.type):
|
|
return self.type(value)
|
|
return value
|
|
|
|
def default(self):
|
|
return copy.deepcopy(self.default_value)
|
|
|
|
|
|
class ValueReference:
|
|
def __init__(self, id, value=None):
|
|
self.value = value
|
|
self.id = id
|
|
|
|
@classmethod
|
|
def from_registry(cls, id, registry: ObjectRegistry):
|
|
return cls(id, registry.get_object(id))
|
|
|
|
|
|
class XmlAttribute(TypedXmlDescriptor):
|
|
def from_xml(self, obj, parent: minidom.Element, registry: ObjectRegistry):
|
|
xml_str = parent.getAttribute(self.name)
|
|
if xml_str:
|
|
if xml_str.startswith(":") and xml_str[1:] in registry.registry:
|
|
value = ValueReference.from_registry(xml_str[1:], registry)
|
|
else:
|
|
value = value_from_xml_string(xml_str, self.type, registry)
|
|
setattr(obj, self.att_name, value)
|
|
|
|
def to_xml(self, obj, parent: minidom.Element, dom: minidom.Document):
|
|
value = getattr(obj, self.att_name)
|
|
if value is not None:
|
|
if isinstance(value, ValueReference):
|
|
xml_str = ":" + value.id
|
|
else:
|
|
xml_str = value_to_xml_string(value, self.type)
|
|
parent.setAttribute(self.name, xml_str)
|
|
|
|
|
|
class XmlFixedAttribute(XmlDescriptor):
|
|
def __init__(self, name, value, type=str):
|
|
super().__init__(name)
|
|
self.value = value
|
|
self.type = type
|
|
|
|
def to_xml(self, obj, parent: minidom.Element, dom: minidom.Document):
|
|
parent.setAttribute(self.name, value_to_xml_string(self.value, self.type))
|
|
|
|
def from_python(self, value):
|
|
if value != self.value:
|
|
raise ValueError("Value of %s should be %s, got %s" % (self.name, self.value, value))
|
|
return value
|
|
|
|
def from_xml(self, obj, parent: minidom.Element, registry: ObjectRegistry):
|
|
xml_str = parent.getAttribute(self.name)
|
|
setattr(obj, self.att_name, value_from_xml_string(xml_str, self.type, registry))
|
|
|
|
def default(self):
|
|
return self.value
|
|
|
|
|
|
class XmlSimpleElement(TypedXmlDescriptor):
|
|
def from_xml(self, obj, parent: minidom.Element, registry: ObjectRegistry):
|
|
cn = xml_first_element_child(parent, self.name, allow_none=True)
|
|
if cn:
|
|
value = value_from_xml_string(xml_text(cn), self.type, registry)
|
|
else:
|
|
value = self.default_value
|
|
|
|
setattr(obj, self.att_name, value)
|
|
|
|
def to_xml(self, obj, parent: minidom.Element, dom: minidom.Document):
|
|
value = getattr(obj, self.att_name)
|
|
if value is not None:
|
|
parent.appendChild(xml_make_text(dom, self.name, value_to_xml_string(value, self.type)))
|
|
|
|
|
|
class XmlMeta(TypedXmlDescriptor):
|
|
def from_xml(self, obj, parent: minidom.Element, registry: ObjectRegistry):
|
|
for cn in xml_child_elements(parent, "meta"):
|
|
if cn.getAttribute("name") == self.name:
|
|
value = value_from_xml_string(cn.getAttribute("content"), self.type, registry)
|
|
break
|
|
else:
|
|
value = self.default_value
|
|
|
|
setattr(obj, self.att_name, value)
|
|
|
|
def to_xml(self, obj, parent: minidom.Element, dom: minidom.Document):
|
|
value = getattr(obj, self.att_name)
|
|
if value is not None:
|
|
meta = parent.appendChild(dom.createElement("meta"))
|
|
meta.setAttribute("name", self.name)
|
|
meta.setAttribute("content", value_to_xml_string(value, self.type))
|