geometry.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  1. # Copyright (c) 2010-2024 openpyxl
  2. from openpyxl.descriptors.serialisable import Serialisable
  3. from openpyxl.descriptors import (
  4. Typed,
  5. Float,
  6. Integer,
  7. Bool,
  8. MinMax,
  9. Set,
  10. NoneSet,
  11. String,
  12. Alias,
  13. )
  14. from openpyxl.descriptors.excel import Coordinate, Percentage
  15. from openpyxl.descriptors.excel import ExtensionList as OfficeArtExtensionList
  16. from .line import LineProperties
  17. from openpyxl.styles.colors import Color
  18. from openpyxl.xml.constants import DRAWING_NS
  19. class Point2D(Serialisable):
  20. tagname = "off"
  21. namespace = DRAWING_NS
  22. x = Coordinate()
  23. y = Coordinate()
  24. def __init__(self,
  25. x=None,
  26. y=None,
  27. ):
  28. self.x = x
  29. self.y = y
  30. class PositiveSize2D(Serialisable):
  31. tagname = "ext"
  32. namespace = DRAWING_NS
  33. """
  34. Dimensions in EMUs
  35. """
  36. cx = Integer()
  37. width = Alias('cx')
  38. cy = Integer()
  39. height = Alias('cy')
  40. def __init__(self,
  41. cx=None,
  42. cy=None,
  43. ):
  44. self.cx = cx
  45. self.cy = cy
  46. class Transform2D(Serialisable):
  47. tagname = "xfrm"
  48. namespace = DRAWING_NS
  49. rot = Integer(allow_none=True)
  50. flipH = Bool(allow_none=True)
  51. flipV = Bool(allow_none=True)
  52. off = Typed(expected_type=Point2D, allow_none=True)
  53. ext = Typed(expected_type=PositiveSize2D, allow_none=True)
  54. chOff = Typed(expected_type=Point2D, allow_none=True)
  55. chExt = Typed(expected_type=PositiveSize2D, allow_none=True)
  56. __elements__ = ('off', 'ext', 'chOff', 'chExt')
  57. def __init__(self,
  58. rot=None,
  59. flipH=None,
  60. flipV=None,
  61. off=None,
  62. ext=None,
  63. chOff=None,
  64. chExt=None,
  65. ):
  66. self.rot = rot
  67. self.flipH = flipH
  68. self.flipV = flipV
  69. self.off = off
  70. self.ext = ext
  71. self.chOff = chOff
  72. self.chExt = chExt
  73. class GroupTransform2D(Serialisable):
  74. tagname = "xfrm"
  75. namespace = DRAWING_NS
  76. rot = Integer(allow_none=True)
  77. flipH = Bool(allow_none=True)
  78. flipV = Bool(allow_none=True)
  79. off = Typed(expected_type=Point2D, allow_none=True)
  80. ext = Typed(expected_type=PositiveSize2D, allow_none=True)
  81. chOff = Typed(expected_type=Point2D, allow_none=True)
  82. chExt = Typed(expected_type=PositiveSize2D, allow_none=True)
  83. __elements__ = ("off", "ext", "chOff", "chExt")
  84. def __init__(self,
  85. rot=0,
  86. flipH=None,
  87. flipV=None,
  88. off=None,
  89. ext=None,
  90. chOff=None,
  91. chExt=None,
  92. ):
  93. self.rot = rot
  94. self.flipH = flipH
  95. self.flipV = flipV
  96. self.off = off
  97. self.ext = ext
  98. self.chOff = chOff
  99. self.chExt = chExt
  100. class SphereCoords(Serialisable):
  101. tagname = "sphereCoords" # usually
  102. lat = Integer()
  103. lon = Integer()
  104. rev = Integer()
  105. def __init__(self,
  106. lat=None,
  107. lon=None,
  108. rev=None,
  109. ):
  110. self.lat = lat
  111. self.lon = lon
  112. self.rev = rev
  113. class Camera(Serialisable):
  114. tagname = "camera"
  115. prst = Set(values=[
  116. 'legacyObliqueTopLeft', 'legacyObliqueTop', 'legacyObliqueTopRight', 'legacyObliqueLeft',
  117. 'legacyObliqueFront', 'legacyObliqueRight', 'legacyObliqueBottomLeft',
  118. 'legacyObliqueBottom', 'legacyObliqueBottomRight', 'legacyPerspectiveTopLeft',
  119. 'legacyPerspectiveTop', 'legacyPerspectiveTopRight', 'legacyPerspectiveLeft',
  120. 'legacyPerspectiveFront', 'legacyPerspectiveRight', 'legacyPerspectiveBottomLeft',
  121. 'legacyPerspectiveBottom', 'legacyPerspectiveBottomRight', 'orthographicFront',
  122. 'isometricTopUp', 'isometricTopDown', 'isometricBottomUp', 'isometricBottomDown',
  123. 'isometricLeftUp', 'isometricLeftDown', 'isometricRightUp', 'isometricRightDown',
  124. 'isometricOffAxis1Left', 'isometricOffAxis1Right', 'isometricOffAxis1Top',
  125. 'isometricOffAxis2Left', 'isometricOffAxis2Right', 'isometricOffAxis2Top',
  126. 'isometricOffAxis3Left', 'isometricOffAxis3Right', 'isometricOffAxis3Bottom',
  127. 'isometricOffAxis4Left', 'isometricOffAxis4Right', 'isometricOffAxis4Bottom',
  128. 'obliqueTopLeft', 'obliqueTop', 'obliqueTopRight', 'obliqueLeft', 'obliqueRight',
  129. 'obliqueBottomLeft', 'obliqueBottom', 'obliqueBottomRight', 'perspectiveFront',
  130. 'perspectiveLeft', 'perspectiveRight', 'perspectiveAbove', 'perspectiveBelow',
  131. 'perspectiveAboveLeftFacing', 'perspectiveAboveRightFacing',
  132. 'perspectiveContrastingLeftFacing', 'perspectiveContrastingRightFacing',
  133. 'perspectiveHeroicLeftFacing', 'perspectiveHeroicRightFacing',
  134. 'perspectiveHeroicExtremeLeftFacing', 'perspectiveHeroicExtremeRightFacing',
  135. 'perspectiveRelaxed', 'perspectiveRelaxedModerately'])
  136. fov = Integer(allow_none=True)
  137. zoom = Typed(expected_type=Percentage, allow_none=True)
  138. rot = Typed(expected_type=SphereCoords, allow_none=True)
  139. def __init__(self,
  140. prst=None,
  141. fov=None,
  142. zoom=None,
  143. rot=None,
  144. ):
  145. self.prst = prst
  146. self.fov = fov
  147. self.zoom = zoom
  148. self.rot = rot
  149. class LightRig(Serialisable):
  150. tagname = "lightRig"
  151. rig = Set(values=['legacyFlat1', 'legacyFlat2', 'legacyFlat3', 'legacyFlat4', 'legacyNormal1',
  152. 'legacyNormal2', 'legacyNormal3', 'legacyNormal4', 'legacyHarsh1',
  153. 'legacyHarsh2', 'legacyHarsh3', 'legacyHarsh4', 'threePt', 'balanced',
  154. 'soft', 'harsh', 'flood', 'contrasting', 'morning', 'sunrise', 'sunset',
  155. 'chilly', 'freezing', 'flat', 'twoPt', 'glow', 'brightRoom']
  156. )
  157. dir = Set(values=(['tl', 't', 'tr', 'l', 'r', 'bl', 'b', 'br']))
  158. rot = Typed(expected_type=SphereCoords, allow_none=True)
  159. def __init__(self,
  160. rig=None,
  161. dir=None,
  162. rot=None,
  163. ):
  164. self.rig = rig
  165. self.dir = dir
  166. self.rot = rot
  167. class Vector3D(Serialisable):
  168. tagname = "vector"
  169. dx = Integer() # can be in or universl measure :-/
  170. dy = Integer()
  171. dz = Integer()
  172. def __init__(self,
  173. dx=None,
  174. dy=None,
  175. dz=None,
  176. ):
  177. self.dx = dx
  178. self.dy = dy
  179. self.dz = dz
  180. class Point3D(Serialisable):
  181. tagname = "anchor"
  182. x = Integer()
  183. y = Integer()
  184. z = Integer()
  185. def __init__(self,
  186. x=None,
  187. y=None,
  188. z=None,
  189. ):
  190. self.x = x
  191. self.y = y
  192. self.z = z
  193. class Backdrop(Serialisable):
  194. anchor = Typed(expected_type=Point3D, )
  195. norm = Typed(expected_type=Vector3D, )
  196. up = Typed(expected_type=Vector3D, )
  197. extLst = Typed(expected_type=OfficeArtExtensionList, allow_none=True)
  198. def __init__(self,
  199. anchor=None,
  200. norm=None,
  201. up=None,
  202. extLst=None,
  203. ):
  204. self.anchor = anchor
  205. self.norm = norm
  206. self.up = up
  207. self.extLst = extLst
  208. class Scene3D(Serialisable):
  209. camera = Typed(expected_type=Camera, )
  210. lightRig = Typed(expected_type=LightRig, )
  211. backdrop = Typed(expected_type=Backdrop, allow_none=True)
  212. extLst = Typed(expected_type=OfficeArtExtensionList, allow_none=True)
  213. def __init__(self,
  214. camera=None,
  215. lightRig=None,
  216. backdrop=None,
  217. extLst=None,
  218. ):
  219. self.camera = camera
  220. self.lightRig = lightRig
  221. self.backdrop = backdrop
  222. self.extLst = extLst
  223. class Bevel(Serialisable):
  224. tagname = "bevel"
  225. w = Integer()
  226. h = Integer()
  227. prst = NoneSet(values=
  228. ['relaxedInset', 'circle', 'slope', 'cross', 'angle',
  229. 'softRound', 'convex', 'coolSlant', 'divot', 'riblet',
  230. 'hardEdge', 'artDeco']
  231. )
  232. def __init__(self,
  233. w=None,
  234. h=None,
  235. prst=None,
  236. ):
  237. self.w = w
  238. self.h = h
  239. self.prst = prst
  240. class Shape3D(Serialisable):
  241. namespace = DRAWING_NS
  242. z = Typed(expected_type=Coordinate, allow_none=True)
  243. extrusionH = Integer(allow_none=True)
  244. contourW = Integer(allow_none=True)
  245. prstMaterial = NoneSet(values=[
  246. 'legacyMatte','legacyPlastic', 'legacyMetal', 'legacyWireframe', 'matte', 'plastic',
  247. 'metal', 'warmMatte', 'translucentPowder', 'powder', 'dkEdge',
  248. 'softEdge', 'clear', 'flat', 'softmetal']
  249. )
  250. bevelT = Typed(expected_type=Bevel, allow_none=True)
  251. bevelB = Typed(expected_type=Bevel, allow_none=True)
  252. extrusionClr = Typed(expected_type=Color, allow_none=True)
  253. contourClr = Typed(expected_type=Color, allow_none=True)
  254. extLst = Typed(expected_type=OfficeArtExtensionList, allow_none=True)
  255. def __init__(self,
  256. z=None,
  257. extrusionH=None,
  258. contourW=None,
  259. prstMaterial=None,
  260. bevelT=None,
  261. bevelB=None,
  262. extrusionClr=None,
  263. contourClr=None,
  264. extLst=None,
  265. ):
  266. self.z = z
  267. self.extrusionH = extrusionH
  268. self.contourW = contourW
  269. self.prstMaterial = prstMaterial
  270. self.bevelT = bevelT
  271. self.bevelB = bevelB
  272. self.extrusionClr = extrusionClr
  273. self.contourClr = contourClr
  274. self.extLst = extLst
  275. class Path2D(Serialisable):
  276. w = Float()
  277. h = Float()
  278. fill = NoneSet(values=(['norm', 'lighten', 'lightenLess', 'darken', 'darkenLess']))
  279. stroke = Bool(allow_none=True)
  280. extrusionOk = Bool(allow_none=True)
  281. def __init__(self,
  282. w=None,
  283. h=None,
  284. fill=None,
  285. stroke=None,
  286. extrusionOk=None,
  287. ):
  288. self.w = w
  289. self.h = h
  290. self.fill = fill
  291. self.stroke = stroke
  292. self.extrusionOk = extrusionOk
  293. class Path2DList(Serialisable):
  294. path = Typed(expected_type=Path2D, allow_none=True)
  295. def __init__(self,
  296. path=None,
  297. ):
  298. self.path = path
  299. class GeomRect(Serialisable):
  300. l = Coordinate()
  301. t = Coordinate()
  302. r = Coordinate()
  303. b = Coordinate()
  304. def __init__(self,
  305. l=None,
  306. t=None,
  307. r=None,
  308. b=None,
  309. ):
  310. self.l = l
  311. self.t = t
  312. self.r = r
  313. self.b = b
  314. class AdjPoint2D(Serialisable):
  315. x = Coordinate()
  316. y = Coordinate()
  317. def __init__(self,
  318. x=None,
  319. y=None,
  320. ):
  321. self.x = x
  322. self.y = y
  323. class ConnectionSite(Serialisable):
  324. ang = MinMax(min=0, max=360) # guess work, can also be a name
  325. pos = Typed(expected_type=AdjPoint2D, )
  326. def __init__(self,
  327. ang=None,
  328. pos=None,
  329. ):
  330. self.ang = ang
  331. self.pos = pos
  332. class ConnectionSiteList(Serialisable):
  333. cxn = Typed(expected_type=ConnectionSite, allow_none=True)
  334. def __init__(self,
  335. cxn=None,
  336. ):
  337. self.cxn = cxn
  338. class AdjustHandleList(Serialisable):
  339. pass
  340. class GeomGuide(Serialisable):
  341. name = String()
  342. fmla = String()
  343. def __init__(self,
  344. name=None,
  345. fmla=None,
  346. ):
  347. self.name = name
  348. self.fmla = fmla
  349. class GeomGuideList(Serialisable):
  350. gd = Typed(expected_type=GeomGuide, allow_none=True)
  351. def __init__(self,
  352. gd=None,
  353. ):
  354. self.gd = gd
  355. class CustomGeometry2D(Serialisable):
  356. avLst = Typed(expected_type=GeomGuideList, allow_none=True)
  357. gdLst = Typed(expected_type=GeomGuideList, allow_none=True)
  358. ahLst = Typed(expected_type=AdjustHandleList, allow_none=True)
  359. cxnLst = Typed(expected_type=ConnectionSiteList, allow_none=True)
  360. #rect = Typed(expected_type=GeomRect, allow_none=True)
  361. pathLst = Typed(expected_type=Path2DList, )
  362. def __init__(self,
  363. avLst=None,
  364. gdLst=None,
  365. ahLst=None,
  366. cxnLst=None,
  367. rect=None,
  368. pathLst=None,
  369. ):
  370. self.avLst = avLst
  371. self.gdLst = gdLst
  372. self.ahLst = ahLst
  373. self.cxnLst = cxnLst
  374. self.rect = None
  375. self.pathLst = pathLst
  376. class PresetGeometry2D(Serialisable):
  377. namespace = DRAWING_NS
  378. prst = Set(values=(
  379. ['line', 'lineInv', 'triangle', 'rtTriangle', 'rect',
  380. 'diamond', 'parallelogram', 'trapezoid', 'nonIsoscelesTrapezoid',
  381. 'pentagon', 'hexagon', 'heptagon', 'octagon', 'decagon', 'dodecagon',
  382. 'star4', 'star5', 'star6', 'star7', 'star8', 'star10', 'star12',
  383. 'star16', 'star24', 'star32', 'roundRect', 'round1Rect',
  384. 'round2SameRect', 'round2DiagRect', 'snipRoundRect', 'snip1Rect',
  385. 'snip2SameRect', 'snip2DiagRect', 'plaque', 'ellipse', 'teardrop',
  386. 'homePlate', 'chevron', 'pieWedge', 'pie', 'blockArc', 'donut',
  387. 'noSmoking', 'rightArrow', 'leftArrow', 'upArrow', 'downArrow',
  388. 'stripedRightArrow', 'notchedRightArrow', 'bentUpArrow',
  389. 'leftRightArrow', 'upDownArrow', 'leftUpArrow', 'leftRightUpArrow',
  390. 'quadArrow', 'leftArrowCallout', 'rightArrowCallout', 'upArrowCallout',
  391. 'downArrowCallout', 'leftRightArrowCallout', 'upDownArrowCallout',
  392. 'quadArrowCallout', 'bentArrow', 'uturnArrow', 'circularArrow',
  393. 'leftCircularArrow', 'leftRightCircularArrow', 'curvedRightArrow',
  394. 'curvedLeftArrow', 'curvedUpArrow', 'curvedDownArrow', 'swooshArrow',
  395. 'cube', 'can', 'lightningBolt', 'heart', 'sun', 'moon', 'smileyFace',
  396. 'irregularSeal1', 'irregularSeal2', 'foldedCorner', 'bevel', 'frame',
  397. 'halfFrame', 'corner', 'diagStripe', 'chord', 'arc', 'leftBracket',
  398. 'rightBracket', 'leftBrace', 'rightBrace', 'bracketPair', 'bracePair',
  399. 'straightConnector1', 'bentConnector2', 'bentConnector3',
  400. 'bentConnector4', 'bentConnector5', 'curvedConnector2',
  401. 'curvedConnector3', 'curvedConnector4', 'curvedConnector5', 'callout1',
  402. 'callout2', 'callout3', 'accentCallout1', 'accentCallout2',
  403. 'accentCallout3', 'borderCallout1', 'borderCallout2', 'borderCallout3',
  404. 'accentBorderCallout1', 'accentBorderCallout2', 'accentBorderCallout3',
  405. 'wedgeRectCallout', 'wedgeRoundRectCallout', 'wedgeEllipseCallout',
  406. 'cloudCallout', 'cloud', 'ribbon', 'ribbon2', 'ellipseRibbon',
  407. 'ellipseRibbon2', 'leftRightRibbon', 'verticalScroll',
  408. 'horizontalScroll', 'wave', 'doubleWave', 'plus', 'flowChartProcess',
  409. 'flowChartDecision', 'flowChartInputOutput',
  410. 'flowChartPredefinedProcess', 'flowChartInternalStorage',
  411. 'flowChartDocument', 'flowChartMultidocument', 'flowChartTerminator',
  412. 'flowChartPreparation', 'flowChartManualInput',
  413. 'flowChartManualOperation', 'flowChartConnector', 'flowChartPunchedCard',
  414. 'flowChartPunchedTape', 'flowChartSummingJunction', 'flowChartOr',
  415. 'flowChartCollate', 'flowChartSort', 'flowChartExtract',
  416. 'flowChartMerge', 'flowChartOfflineStorage', 'flowChartOnlineStorage',
  417. 'flowChartMagneticTape', 'flowChartMagneticDisk',
  418. 'flowChartMagneticDrum', 'flowChartDisplay', 'flowChartDelay',
  419. 'flowChartAlternateProcess', 'flowChartOffpageConnector',
  420. 'actionButtonBlank', 'actionButtonHome', 'actionButtonHelp',
  421. 'actionButtonInformation', 'actionButtonForwardNext',
  422. 'actionButtonBackPrevious', 'actionButtonEnd', 'actionButtonBeginning',
  423. 'actionButtonReturn', 'actionButtonDocument', 'actionButtonSound',
  424. 'actionButtonMovie', 'gear6', 'gear9', 'funnel', 'mathPlus', 'mathMinus',
  425. 'mathMultiply', 'mathDivide', 'mathEqual', 'mathNotEqual', 'cornerTabs',
  426. 'squareTabs', 'plaqueTabs', 'chartX', 'chartStar', 'chartPlus']))
  427. avLst = Typed(expected_type=GeomGuideList, allow_none=True)
  428. def __init__(self,
  429. prst=None,
  430. avLst=None,
  431. ):
  432. self.prst = prst
  433. self.avLst = avLst
  434. class FontReference(Serialisable):
  435. idx = NoneSet(values=(['major', 'minor']))
  436. def __init__(self,
  437. idx=None,
  438. ):
  439. self.idx = idx
  440. class StyleMatrixReference(Serialisable):
  441. idx = Integer()
  442. def __init__(self,
  443. idx=None,
  444. ):
  445. self.idx = idx
  446. class ShapeStyle(Serialisable):
  447. lnRef = Typed(expected_type=StyleMatrixReference, )
  448. fillRef = Typed(expected_type=StyleMatrixReference, )
  449. effectRef = Typed(expected_type=StyleMatrixReference, )
  450. fontRef = Typed(expected_type=FontReference, )
  451. def __init__(self,
  452. lnRef=None,
  453. fillRef=None,
  454. effectRef=None,
  455. fontRef=None,
  456. ):
  457. self.lnRef = lnRef
  458. self.fillRef = fillRef
  459. self.effectRef = effectRef
  460. self.fontRef = fontRef