aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/fonttools/fontTools/misc
diff options
context:
space:
mode:
authorrobot-piglet <robot-piglet@yandex-team.com>2024-06-08 08:51:43 +0300
committerrobot-piglet <robot-piglet@yandex-team.com>2024-06-08 09:02:27 +0300
commitc3763910c6f878b17102c94e0b62cab57c9954b8 (patch)
tree19de35706beeb1adc158f13ca87110e110f1a753 /contrib/python/fonttools/fontTools/misc
parent63965219325c32d9b72b466b89fc613295746336 (diff)
downloadydb-c3763910c6f878b17102c94e0b62cab57c9954b8.tar.gz
Intermediate changes
Diffstat (limited to 'contrib/python/fonttools/fontTools/misc')
-rw-r--r--contrib/python/fonttools/fontTools/misc/bezierTools.py5
-rw-r--r--contrib/python/fonttools/fontTools/misc/iterTools.py12
-rw-r--r--contrib/python/fonttools/fontTools/misc/lazyTools.py42
-rw-r--r--contrib/python/fonttools/fontTools/misc/psCharStrings.py20
-rw-r--r--contrib/python/fonttools/fontTools/misc/sstruct.py21
-rw-r--r--contrib/python/fonttools/fontTools/misc/transform.py13
6 files changed, 107 insertions, 6 deletions
diff --git a/contrib/python/fonttools/fontTools/misc/bezierTools.py b/contrib/python/fonttools/fontTools/misc/bezierTools.py
index a1a707b098..5411ff99fd 100644
--- a/contrib/python/fonttools/fontTools/misc/bezierTools.py
+++ b/contrib/python/fonttools/fontTools/misc/bezierTools.py
@@ -18,6 +18,9 @@ except (AttributeError, ImportError):
COMPILED = False
+EPSILON = 1e-9
+
+
Intersection = namedtuple("Intersection", ["pt", "t1", "t2"])
@@ -92,7 +95,7 @@ def _split_cubic_into_two(p0, p1, p2, p3):
def _calcCubicArcLengthCRecurse(mult, p0, p1, p2, p3):
arch = abs(p0 - p3)
box = abs(p0 - p1) + abs(p1 - p2) + abs(p2 - p3)
- if arch * mult >= box:
+ if arch * mult + EPSILON >= box:
return (arch + box) * 0.5
else:
one, two = _split_cubic_into_two(p0, p1, p2, p3)
diff --git a/contrib/python/fonttools/fontTools/misc/iterTools.py b/contrib/python/fonttools/fontTools/misc/iterTools.py
new file mode 100644
index 0000000000..d7b8305322
--- /dev/null
+++ b/contrib/python/fonttools/fontTools/misc/iterTools.py
@@ -0,0 +1,12 @@
+from itertools import *
+
+# Python 3.12:
+if "batched" not in globals():
+ # https://docs.python.org/3/library/itertools.html#itertools.batched
+ def batched(iterable, n):
+ # batched('ABCDEFG', 3) --> ABC DEF G
+ if n < 1:
+ raise ValueError("n must be at least one")
+ it = iter(iterable)
+ while batch := tuple(islice(it, n)):
+ yield batch
diff --git a/contrib/python/fonttools/fontTools/misc/lazyTools.py b/contrib/python/fonttools/fontTools/misc/lazyTools.py
new file mode 100644
index 0000000000..91cb80c992
--- /dev/null
+++ b/contrib/python/fonttools/fontTools/misc/lazyTools.py
@@ -0,0 +1,42 @@
+from collections import UserDict, UserList
+
+__all__ = ["LazyDict", "LazyList"]
+
+
+class LazyDict(UserDict):
+ def __init__(self, data):
+ super().__init__()
+ self.data = data
+
+ def __getitem__(self, k):
+ v = self.data[k]
+ if callable(v):
+ v = v(k)
+ self.data[k] = v
+ return v
+
+
+class LazyList(UserList):
+ def __getitem__(self, k):
+ if isinstance(k, slice):
+ indices = range(*k.indices(len(self)))
+ return [self[i] for i in indices]
+ v = self.data[k]
+ if callable(v):
+ v = v(k)
+ self.data[k] = v
+ return v
+
+ def __add__(self, other):
+ if isinstance(other, LazyList):
+ other = list(other)
+ elif isinstance(other, list):
+ pass
+ else:
+ return NotImplemented
+ return list(self) + other
+
+ def __radd__(self, other):
+ if not isinstance(other, list):
+ return NotImplemented
+ return other + list(self)
diff --git a/contrib/python/fonttools/fontTools/misc/psCharStrings.py b/contrib/python/fonttools/fontTools/misc/psCharStrings.py
index cc9ca01c7f..5d881c5816 100644
--- a/contrib/python/fonttools/fontTools/misc/psCharStrings.py
+++ b/contrib/python/fonttools/fontTools/misc/psCharStrings.py
@@ -275,6 +275,24 @@ def encodeFloat(f):
s = s[1:]
elif s[:3] == "-0.":
s = "-" + s[2:]
+ elif s.endswith("000"):
+ significantDigits = s.rstrip("0")
+ s = "%sE%d" % (significantDigits, len(s) - len(significantDigits))
+ else:
+ dotIndex = s.find(".")
+ eIndex = s.find("E")
+ if dotIndex != -1 and eIndex != -1:
+ integerPart = s[:dotIndex]
+ fractionalPart = s[dotIndex + 1 : eIndex]
+ exponent = int(s[eIndex + 1 :])
+ newExponent = exponent - len(fractionalPart)
+ if newExponent == 1:
+ s = "%s%s0" % (integerPart, fractionalPart)
+ else:
+ s = "%s%sE%d" % (integerPart, fractionalPart, newExponent)
+ if s.startswith((".0", "-.0")):
+ sign, s = s.split(".", 1)
+ s = "%s%sE-%d" % (sign, s.lstrip("0"), len(s))
nibbles = []
while s:
c = s[0]
@@ -286,6 +304,8 @@ def encodeFloat(f):
c = "E-"
elif c2 == "+":
s = s[1:]
+ if s.startswith("0"):
+ s = s[1:]
nibbles.append(realNibblesDict[c])
nibbles.append(0xF)
if len(nibbles) % 2:
diff --git a/contrib/python/fonttools/fontTools/misc/sstruct.py b/contrib/python/fonttools/fontTools/misc/sstruct.py
index d35bc9a5c8..92be275b89 100644
--- a/contrib/python/fonttools/fontTools/misc/sstruct.py
+++ b/contrib/python/fonttools/fontTools/misc/sstruct.py
@@ -64,7 +64,10 @@ def pack(fmt, obj):
elements = []
if not isinstance(obj, dict):
obj = obj.__dict__
- for name in names:
+ string_index = formatstring
+ if formatstring.startswith(">"):
+ string_index = formatstring[1:]
+ for ix, name in enumerate(names.keys()):
value = obj[name]
if name in fixes:
# fixed point conversion
@@ -72,6 +75,13 @@ def pack(fmt, obj):
elif isinstance(value, str):
value = tobytes(value)
elements.append(value)
+ # Check it fits
+ try:
+ struct.pack(names[name], value)
+ except Exception as e:
+ raise ValueError(
+ "Value %s does not fit in format %s for %s" % (value, names[name], name)
+ ) from e
data = struct.pack(*(formatstring,) + tuple(elements))
return data
@@ -87,7 +97,7 @@ def unpack(fmt, data, obj=None):
d = obj.__dict__
elements = struct.unpack(formatstring, data)
for i in range(len(names)):
- name = names[i]
+ name = list(names.keys())[i]
value = elements[i]
if name in fixes:
# fixed point conversion
@@ -141,7 +151,7 @@ def getformat(fmt, keep_pad_byte=False):
except KeyError:
lines = re.split("[\n;]", fmt)
formatstring = ""
- names = []
+ names = {}
fixes = {}
for line in lines:
if _emptyRE.match(line):
@@ -158,7 +168,7 @@ def getformat(fmt, keep_pad_byte=False):
name = m.group(1)
formatchar = m.group(2)
if keep_pad_byte or formatchar != "x":
- names.append(name)
+ names[name] = formatchar
if m.group(3):
# fixed point
before = int(m.group(3))
@@ -167,9 +177,10 @@ def getformat(fmt, keep_pad_byte=False):
if bits not in [8, 16, 32]:
raise Error("fixed point must be 8, 16 or 32 bits long")
formatchar = _fixedpointmappings[bits]
+ names[name] = formatchar
assert m.group(5) == "F"
fixes[name] = after
- formatstring = formatstring + formatchar
+ formatstring += formatchar
_formatcache[fmt] = formatstring, names, fixes
return formatstring, names, fixes
diff --git a/contrib/python/fonttools/fontTools/misc/transform.py b/contrib/python/fonttools/fontTools/misc/transform.py
index 0f9f3a5d8b..9025b79ec1 100644
--- a/contrib/python/fonttools/fontTools/misc/transform.py
+++ b/contrib/python/fonttools/fontTools/misc/transform.py
@@ -422,6 +422,19 @@ class DecomposedTransform:
tCenterX: float = 0
tCenterY: float = 0
+ def __bool__(self):
+ return (
+ self.translateX != 0
+ or self.translateY != 0
+ or self.rotation != 0
+ or self.scaleX != 1
+ or self.scaleY != 1
+ or self.skewX != 0
+ or self.skewY != 0
+ or self.tCenterX != 0
+ or self.tCenterY != 0
+ )
+
@classmethod
def fromTransform(self, transform):
# Adapted from an answer on