geometry.py 17 KB

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