-
Notifications
You must be signed in to change notification settings - Fork 23
/
passepartout.py
172 lines (146 loc) · 6.64 KB
/
passepartout.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# SPDX-License-Identifier:LGPL-3.0-only or GPL-3.0-only
# In this file it is permitted to catch exceptions on a broad basis since there
# are many things that can go wrong with file handling and parsing:
# pylint: disable=bare-except,broad-except
# We're not quite at the level of documenting all the classes and functions yet :-)
# pylint: disable=missing-function-docstring,missing-class-docstring,missing-module-docstring
# Copyright (c) 2020 by BarchSteel
from pathlib import Path
import os
import os.path
import cairosvg
import PIL
import logging
from PIL.ExifTags import TAGS
from io import BytesIO
from clpFile import ClpFile
from typing import List, Set, Dict, Tuple, Optional
from lxml import etree
from typing import NamedTuple
configlogger = logging.getLogger("cewe2pdf.config")
class Passepartout(object):
def __init__(self):
return
class decorationXmlInfo(NamedTuple):
srcXmlFile: str
designElementId: int
decoration_id: str
decoration_type: str
designElementType: str
maskFile: str
clipartFile: str
fotoarea_height: float
fotoarea_width: float
fotoarea_x: float
fotoarea_y: float
@staticmethod
def extractInfoFromXml(xmlFileName: str, passepartoutid: int):
for xmlInfo in Passepartout.extractAllInfosFromXml(xmlFileName):
if xmlInfo.designElementId == passepartoutid:
return xmlInfo
return None
@staticmethod
def extractAllInfosFromXml(xmlFileName: str):
# read information from xml file about passepartout
clipArtXml = open(xmlFileName, 'rb')
try:
xmlInfo = etree.parse(xmlFileName)
except: # noqa: E722
logging.error("Maybe not valid XML:{}".format(xmlFileName))
return None
finally:
clipArtXml.close()
for decoration in xmlInfo.findall('decoration'):
decoration_id = decoration.get('id')
decoration_type = decoration.get('type')
# decoration_type is often "fading", so typeElement is then looking for <fading .../>
typeElement = decoration.find(decoration_type)
if typeElement is None:
continue
# assume these IDs are always integers.
designElementId = decoration.get('designElementId')
if designElementId is None:
designElementId = typeElement.get('designElementId')
if designElementId is None:
continue
designElementId = int(designElementId)
designElementType = typeElement.get('designElementType')
maskFile = typeElement.get('file')
clipartElement = typeElement.find('clipart')
if clipartElement is not None:
clipartFile = clipartElement.get('file')
else:
clipartFile = None
fotoareaElement = typeElement.find('fotoarea')
if fotoareaElement is not None:
fotoarea_height = float(fotoareaElement.get('height'))
fotoarea_width = float(fotoareaElement.get('width'))
fotoarea_x = float(fotoareaElement.get('x'))
fotoarea_y = float(fotoareaElement.get('y'))
else:
fotoarea_height = None
fotoarea_width = None
fotoarea_x = None
fotoarea_y = None
yield Passepartout.decorationXmlInfo(xmlFileName, designElementId, decoration_id, decoration_type,
designElementType, maskFile, clipartFile,
fotoarea_height, fotoarea_width, fotoarea_x, fotoarea_y)
return None
@staticmethod
def buildElementIdIndex(directoryList: List[str]) -> dict:
# go through directories and search for .xml files and build a dictionary of
# designElementId to .xml file
# a dictionary for passepartout element IDs to file name
passepartoutIdDict = dict()
if directoryList is None:
configlogger.error("No directories passed to Passepartout.buildElementIdIndex!")
return passepartoutIdDict
if isinstance(directoryList, tuple):
directoryList = list(directoryList)
if not isinstance(directoryList, list):
directoryList = [directoryList]
configlogger.info("Refreshing decoration designElementId index.")
# generate list of .xml files
xmlFileList = []
ext = ".xml"
for path in directoryList:
for dirpath, dirnames, filenames in os.walk(path): # dirnames pylint: disable=unused-variable
for filename in (f for f in filenames if f.endswith(ext)):
xmlFileList.append(os.path.join(dirpath, filename))
# print(os.path.join(dirpath, filename))
configlogger.info("Found {:d} XML files.".format(len(xmlFileList)))
# load each .xml file and extract the information
for curXmlFile in xmlFileList:
# print("Parsing passepartout: {}".format(curXmlFile))
for xmlInfo in Passepartout.extractAllInfosFromXml(curXmlFile):
if xmlInfo is None:
continue # this .xml file is not for a passepartout, or something went wrong
if xmlInfo.designElementType == 'passepartout':
# print("Adding passepartout to dict: {}".format(curXmlFile))
passepartoutIdDict[xmlInfo.designElementId] = curXmlFile
return passepartoutIdDict
@staticmethod
def getPassepartoutFileFullName(xmlInfo:decorationXmlInfo, fileName:str) -> str:
if fileName is None:
return None
pathObj = Path(xmlInfo.srcXmlFile)
# should not be needed: pathObj = pathObj.resolve() # convert it to an absolute path
basePath = pathObj.parent
fullPath = basePath.joinpath(fileName)
return str(fullPath)
@staticmethod
def getClipartFullName(xmlInfo:decorationXmlInfo) -> str:
return Passepartout.getPassepartoutFileFullName(xmlInfo, xmlInfo.clipartFile)
@staticmethod
def getMaskFullName(xmlInfo:decorationXmlInfo) -> str:
return Passepartout.getPassepartoutFileFullName(xmlInfo, xmlInfo.maskFile)
if __name__ == '__main__':
# only executed when this file is run directly.
myDict = Passepartout.buildElementIdIndex(
[r"C:\ProgramData\hps\1320",
"C:/Program Files/dm/dm-Fotowelt/Resources/photofun/decorations"])
testId = 125186
testXmlInfo = Passepartout.extractInfoFromXml(myDict[testId], testId)
print(testId)
print(testXmlInfo)
print(Passepartout.getClipartFullName(testXmlInfo))