forked from scanny/python-pptx
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathutil.py
More file actions
179 lines (144 loc) · 4.38 KB
/
util.py
File metadata and controls
179 lines (144 loc) · 4.38 KB
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
173
174
175
176
177
178
179
# encoding: utf-8
"""
Utility functions and classes that come in handy when working with PowerPoint
and Open XML.
"""
from __future__ import absolute_import, division, print_function
import platform
from warnings import warn
class Length(int):
"""
Base class for length classes Inches, Emu, Cm, Mm, Pt, and Px. Provides
properties for converting length values to convenient units.
"""
_EMUS_PER_INCH = 914400
_EMUS_PER_CENTIPOINT = 127
_EMUS_PER_CM = 360000
_EMUS_PER_MM = 36000
_EMUS_PER_PT = 12700
_EMUS_PER_PX = 9525 if platform.system() == 'Windows' else 12700
def __new__(cls, emu):
return int.__new__(cls, emu)
@property
def inches(self):
"""
Floating point length in inches
"""
return self / float(self._EMUS_PER_INCH)
@property
def centipoints(self):
"""
Integer length in hundredths of a point (1/7200 inch). Used
internally because PowerPoint stores font size in centipoints.
"""
return self // self._EMUS_PER_CENTIPOINT
@property
def cm(self):
"""
Floating point length in centimeters
"""
return self / float(self._EMUS_PER_CM)
@property
def emu(self):
"""
Integer length in English Metric Units
"""
return self
@property
def mm(self):
"""
Floating point length in millimeters
"""
return self / float(self._EMUS_PER_MM)
@property
def pt(self):
"""
Floating point length in points
"""
return self / float(self._EMUS_PER_PT)
@property
def px(self):
"""
Integer length in pixels. Note this value is platform dependent,
using 96 pixels/inch on Windows, 72 pixels/inch on all other
platforms.
"""
msg = (
'Length.px property is deprecated and will be removed in a futur'
'e release.'
)
warn(msg, UserWarning, stacklevel=2)
# round can somtimes return values like x.999999 which are truncated
# to x by int(); adding the 0.1 prevents this
return int(round(self / float(self._EMUS_PER_PX)) + 0.1)
class Inches(Length):
"""
Convenience constructor for length in inches
"""
def __new__(cls, inches):
emu = int(inches * Length._EMUS_PER_INCH)
return Length.__new__(cls, emu)
class Centipoints(Length):
"""
Convenience constructor for length in hundredths of a point
"""
def __new__(cls, centipoints):
emu = int(centipoints * Length._EMUS_PER_CENTIPOINT)
return Length.__new__(cls, emu)
class Cm(Length):
"""
Convenience constructor for length in centimeters
"""
def __new__(cls, cm):
emu = int(cm * Length._EMUS_PER_CM)
return Length.__new__(cls, emu)
class Emu(Length):
"""
Convenience constructor for length in english metric units
"""
def __new__(cls, emu):
return Length.__new__(cls, int(emu))
class Mm(Length):
"""
Convenience constructor for length in millimeters
"""
def __new__(cls, mm):
emu = int(mm * Length._EMUS_PER_MM)
return Length.__new__(cls, emu)
class Pt(Length):
"""
Convenience value class for specifying a length in points
"""
def __new__(cls, points):
emu = int(points * Length._EMUS_PER_PT)
return Length.__new__(cls, emu)
class Px(Length):
"""
Convenience constructor for length in pixels
"""
def __new__(cls, px):
"""
Deprecated. Use one of the other Length classes.
"""
msg = (
'Px class is deprecated and will be removed in a future release.'
)
warn(msg, UserWarning, stacklevel=2)
emu = int(px * Length._EMUS_PER_PX)
return Length.__new__(cls, emu)
def lazyproperty(f):
"""
@lazyprop decorator. Decorated method will be called only on first access
to calculate a cached property value. After that, the cached value is
returned.
"""
cache_attr_name = '_%s' % f.__name__ # like '_foobar' for prop 'foobar'
docstring = f.__doc__
def get_prop_value(obj):
try:
return getattr(obj, cache_attr_name)
except AttributeError:
value = f(obj)
setattr(obj, cache_attr_name, value)
return value
return property(get_prop_value, doc=docstring)