From 4a498d7922456c277ab2240145241fa9ffc4c263 Mon Sep 17 00:00:00 2001 From: Roberto Arista Date: Thu, 8 May 2025 17:38:08 +0200 Subject: [PATCH 01/29] add missing return type hints --- drawBot/drawBotDrawingTools.py | 164 +++++++++++++++++++-------------- 1 file changed, 94 insertions(+), 70 deletions(-) diff --git a/drawBot/drawBotDrawingTools.py b/drawBot/drawBotDrawingTools.py index 885478cb..2476f578 100644 --- a/drawBot/drawBotDrawingTools.py +++ b/drawBot/drawBotDrawingTools.py @@ -8,7 +8,7 @@ import AppKit # type: ignore import CoreText # type: ignore import Quartz # type: ignore - +from .drawBotPageDrawingTools import DrawBotPage from .aliases import ( BoundingBox, CMYKColor, @@ -160,7 +160,7 @@ def _copy(self): new._tempInstalledFonts = dict(self._tempInstalledFonts) return new - def newDrawing(self): + def newDrawing(self) -> None: """ Reset the drawing stack to the clean and empty stack. @@ -181,7 +181,7 @@ def newDrawing(self): """ self._reset() - def endDrawing(self): + def endDrawing(self) -> None: """ Explicitly tell drawBot the drawing is done. This is advised when using drawBot as a standalone module. @@ -257,7 +257,7 @@ def pageCount(self) -> int: # size and pages - def size(self, width: float | str, height: float | None = None): + def size(self, width: float | str, height: float | None = None) -> None: """ Set the width and height of the canvas. Without calling `size()` the default drawing board is 1000 by 1000 points. @@ -299,7 +299,7 @@ def size(self, width: float | str, height: float | None = None): else: raise DrawBotError("Can't use 'size()' after drawing has begun. Try to move it to the top of your script.") - def newPage(self, width: str | float | None = None, height: float | None = None): + def newPage(self, width: str | float | None = None, height: float | None = None) -> None: """ Create a new canvas to draw in. This will act like a page in a pdf or a frame in a mov. @@ -338,7 +338,7 @@ def newPage(self, width: str | float | None = None, height: float | None = None) self._dummyContext = DummyContext() self._addInstruction("newPage", width, height) - def pages(self): + def pages(self) -> tuple[DrawBotPage, ...]: """ Return all pages. @@ -380,8 +380,6 @@ def pages(self): # draw an oval in each of them oval(110, 10, 30, 30) """ - from .drawBotPageDrawingTools import DrawBotPage - instructions = [] for instructionSet in self._instructionsStack: for callback, _, _ in instructionSet: @@ -476,7 +474,7 @@ def saveImage(self, path: SomePath, *args, **options: dict[str, Any]): supportedOptions="\n ".join(getContextOptionsDocs()), ) - def printImage(self, pdf=None): + def printImage(self, pdf=None) -> None: """ Export the canvas to a printing dialog, ready to print. @@ -510,7 +508,7 @@ def pdfImage(self): # graphics state - def save(self): + def save(self) -> None: """ DrawBot strongly recommends to use `savedState()` in a `with` statement instead. @@ -522,7 +520,7 @@ def save(self): self._requiresNewFirstPage = True self._addInstruction("save") - def restore(self): + def restore(self) -> None: """ DrawBot strongly recommends to use `savedState()` in a `with` statement instead. @@ -565,7 +563,7 @@ def savedState(self): # basic shapes - def rect(self, x: float, y: float, w: float, h: float): + def rect(self, x: float, y: float, w: float, h: float) -> None: """ Draw a rectangle from position x, y with the given width and height. @@ -578,7 +576,7 @@ def rect(self, x: float, y: float, w: float, h: float): self._requiresNewFirstPage = True self._addInstruction("rect", x, y, w, h) - def oval(self, x: float, y: float, w: float, h: float): + def oval(self, x: float, y: float, w: float, h: float) -> None: """ Draw an oval from position x, y with the given width and height. @@ -593,14 +591,14 @@ def oval(self, x: float, y: float, w: float, h: float): # path - def newPath(self): + def newPath(self) -> None: """ Create a new path. """ self._requiresNewFirstPage = True self._addInstruction("newPath") - def moveTo(self, xy: Point): + def moveTo(self, xy: Point) -> None: """ Move to a point `x`, `y`. """ @@ -608,7 +606,7 @@ def moveTo(self, xy: Point): self._requiresNewFirstPage = True self._addInstruction("moveTo", (x, y)) - def lineTo(self, xy: Point): + def lineTo(self, xy: Point) -> None: """ Line to a point `x`, `y`. """ @@ -616,7 +614,7 @@ def lineTo(self, xy: Point): self._requiresNewFirstPage = True self._addInstruction("lineTo", (x, y)) - def curveTo(self, xy1: Point, xy2: Point, xy3: Point): + def curveTo(self, xy1: Point, xy2: Point, xy3: Point) -> None: """ Curve to a point `x3`, `y3`. With given bezier handles `x1`, `y1` and `x2`, `y2`. @@ -627,7 +625,7 @@ def curveTo(self, xy1: Point, xy2: Point, xy3: Point): self._requiresNewFirstPage = True self._addInstruction("curveTo", (x1, y1), (x2, y2), (x3, y3)) - def qCurveTo(self, *points: Point): + def qCurveTo(self, *points: Point) -> None: """ Quadratic curve with a given set of off curves to a on curve. """ @@ -641,14 +639,14 @@ def arc( startAngle: float, endAngle: float, clockwise: bool, - ): + ) -> None: """ Arc with `center` and a given `radius`, from `startAngle` to `endAngle`, going clockwise if `clockwise` is True and counter clockwise if `clockwise` is False. """ self._requiresNewFirstPage = True self._addInstruction("arc", center, radius, startAngle, endAngle, clockwise) - def arcTo(self, xy1: Point, xy2: Point, radius: float): + def arcTo(self, xy1: Point, xy2: Point, radius: float) -> None: """ Arc from one point to an other point with a given `radius`. @@ -688,14 +686,14 @@ def drawPt(pos, r=5): self._requiresNewFirstPage = True self._addInstruction("arcTo", (x1, y1), (x2, y2), radius) - def closePath(self): + def closePath(self) -> None: """ Close the path. """ self._requiresNewFirstPage = True self._addInstruction("closePath") - def drawPath(self, path: BezierPath | None = None): + def drawPath(self, path: BezierPath | None = None) -> None: """ Draw the current path, or draw the provided path. @@ -724,7 +722,7 @@ def drawPath(self, path: BezierPath | None = None): self._requiresNewFirstPage = True self._addInstruction("drawPath", path) - def clipPath(self, path=None): + def clipPath(self, path=None) -> None: """ Use the given path as a clipping path, or the current path if no path was given. @@ -756,7 +754,7 @@ def clipPath(self, path=None): self._requiresNewFirstPage = True self._addInstruction("clipPath", path) - def line(self, point1: Point, point2: Point): + def line(self, point1: Point, point2: Point) -> None: """ Draws a line between two given points. @@ -771,7 +769,7 @@ def line(self, point1: Point, point2: Point): path.line(point1, point2) self.drawPath(path) - def polygon(self, *points: Point, **kwargs: bool): + def polygon(self, *points: Point, **kwargs: bool) -> None: """ Draws a polygon with n-amount of points. Optionally a `close` argument can be provided to open or close the path. @@ -788,7 +786,7 @@ def polygon(self, *points: Point, **kwargs: bool): # color - def colorSpace(self, colorSpace): + def colorSpace(self, colorSpace) -> None: """ Set the color space. Options are `genericRGB`, `adobeRGB1998`, `sRGB`, `genericGray`, `genericGamma22Gray`. @@ -826,7 +824,7 @@ def listColorSpaces(self) -> list[str]: """ return sorted(self._dummyContext._colorSpaceMap.keys()) - def blendMode(self, operation: str): + def blendMode(self, operation: str) -> None: """ Set a blend mode. @@ -862,7 +860,7 @@ def fill( g: float | None = None, b: float | None = None, alpha: float = 1, - ): + ) -> None: """ Sets the fill color with a `red`, `green`, `blue` and `alpha` value. Each argument must a value float between 0 and 1. @@ -902,7 +900,7 @@ def stroke( g: float | None = None, b: float | None = None, alpha: float = 1, - ): + ) -> None: """ Sets the stroke color with a `red`, `green`, `blue` and `alpha` value. Each argument must a value float between 0 and 1. @@ -947,7 +945,7 @@ def cmykFill( y: float | None = None, k: float | None = None, alpha: float = 1, - ): + ) -> None: """ Set a fill using a CMYK color before drawing a shape. This is handy if the file is intended for print. @@ -978,7 +976,7 @@ def cmykStroke( y: float | None = None, k: float | None = None, alpha: float = 1, - ): + ) -> None: """ Set a stroke using a CMYK color before drawing a shape. This is handy if the file is intended for print. @@ -1006,7 +1004,7 @@ def cmykStroke( self._requiresNewFirstPage = True self._addInstruction("cmykStroke", c, m, y, k, alpha) - def opacity(self, value: float): + def opacity(self, value: float) -> None: """ Sets the current opacity value. The `value` argument must be a value between 0.0 and 1.0. @@ -1031,7 +1029,7 @@ def shadow( offset: Point, blur: float | None = None, color: tuple[float, ...] | None = None, - ): + ) -> None: """ Adds a shadow with an `offset` (x, y), `blur` and a `color`. The `color` argument must be a tuple similarly as `fill`. @@ -1056,7 +1054,7 @@ def cmykShadow( offset: Point, blur: float | None = None, color: tuple[float, ...] | None = None, - ): + ) -> None: """ Adds a cmyk shadow with an `offset` (x, y), `blur` and a `color`. The `color` argument must be a tuple similarly as `cmykFill`. @@ -1113,7 +1111,7 @@ def cmykLinearGradient( endPoint: Point | None = None, colors: list[CMYKColorTuple] | None = None, locations=None, - ): + ) -> None: """ A cmyk linear gradient fill with: @@ -1147,7 +1145,7 @@ def radialGradient( locations: list[float] | None = None, startRadius: float = 0, endRadius: float = 100, - ): + ) -> None: """ A radial gradient fill with: @@ -1185,7 +1183,7 @@ def cmykRadialGradient( locations: list[float] | None = None, startRadius: float = 0, endRadius: float = 100, - ): + ) -> None: """ A cmyk radial gradient fill with: @@ -1217,7 +1215,7 @@ def cmykRadialGradient( # path drawing behavoir - def strokeWidth(self, value: float): + def strokeWidth(self, value: float) -> None: """ Sets stroke width. @@ -1239,7 +1237,7 @@ def strokeWidth(self, value: float): self._requiresNewFirstPage = True self._addInstruction("strokeWidth", value) - def miterLimit(self, value: float): + def miterLimit(self, value: float) -> None: """ Set a miter limit. Used on corner points. @@ -1393,7 +1391,7 @@ def lineDash(self, value: float | None, *values: float, offset: float = 0): # transform - def transform(self, matrix: TransformTuple, center: Point = (0, 0)): + def transform(self, matrix: TransformTuple, center: Point = (0, 0)) -> None: """ Transform the canvas with a transformation matrix. """ @@ -1402,13 +1400,13 @@ def transform(self, matrix: TransformTuple, center: Point = (0, 0)): matrix = transformationAtCenter(matrix, center) self._addInstruction("transform", matrix) - def translate(self, x: float = 0, y: float = 0): + def translate(self, x: float = 0, y: float = 0) -> None: """ Translate the canvas with a given offset. """ self.transform((1, 0, 0, 1, x, y)) - def rotate(self, angle: float, center: Point = (0, 0)): + def rotate(self, angle: float, center: Point = (0, 0)) -> None: """ Rotate the canvas around the `center` point (which is the origin by default) with a given angle in degrees. """ @@ -1417,7 +1415,7 @@ def rotate(self, angle: float, center: Point = (0, 0)): s = math.sin(angle) self.transform((c, s, -s, c, 0, 0), center) - def scale(self, x: float = 1, y: float | None = None, center: Point = (0, 0)): + def scale(self, x: float = 1, y: float | None = None, center: Point = (0, 0)) -> None: """ Scale the canvas with a given `x` (horizontal scale) and `y` (vertical scale). @@ -1429,7 +1427,7 @@ def scale(self, x: float = 1, y: float | None = None, center: Point = (0, 0)): y = x self.transform((x, 0, 0, y, 0, 0), center) - def skew(self, angle1: float, angle2: float = 0, center: Point = (0, 0)): + def skew(self, angle1: float, angle2: float = 0, center: Point = (0, 0)) -> None: """ Skew the canvas with given `angle1` and `angle2`. @@ -1443,7 +1441,12 @@ def skew(self, angle1: float, angle2: float = 0, center: Point = (0, 0)): # text - def font(self, fontNameOrPath: SomePath, fontSize: float | None = None, fontNumber: int = 0): + def font( + self, + fontNameOrPath: SomePath, + fontSize: float | None = None, + fontNumber: int = 0, + ) -> str | None: """ Set a font with the name of the font. If a font path is given the font will be installed and used directly. @@ -1465,7 +1468,7 @@ def font(self, fontNameOrPath: SomePath, fontSize: float | None = None, fontNumb self._addInstruction("font", fontNameOrPath, fontSize, fontNumber) return getFontName(font) - def fallbackFont(self, fontNameOrPath: SomePath, fontNumber: int = 0): + def fallbackFont(self, fontNameOrPath: SomePath, fontNumber: int = 0) -> str | None: """ Set a fallback font, this is used whenever a glyph is not available in the current font. @@ -1480,7 +1483,7 @@ def fallbackFont(self, fontNameOrPath: SomePath, fontNumber: int = 0): self._addInstruction("fallbackFont", fontNameOrPath, fontNumber) return getFontName(dummyFont) - def fontSize(self, fontSize: float): + def fontSize(self, fontSize: float) -> None: """ Set the font size in points. The default `fontSize` is 10pt. @@ -1508,7 +1511,7 @@ def lineHeight(self, value): self._dummyContext.lineHeight(value) self._addInstruction("lineHeight", value) - def tracking(self, value: float): + def tracking(self, value: float) -> None: """ Set the tracking between characters. It adds an absolute number of points between the characters. @@ -1530,14 +1533,14 @@ def tracking(self, value: float): self._dummyContext.tracking(value) self._addInstruction("tracking", value) - def baselineShift(self, value): + def baselineShift(self, value) -> None: """ Set the shift of the baseline. """ self._dummyContext.baselineShift(value) self._addInstruction("baselineShift", value) - def underline(self, value: str): + def underline(self, value: str | None) -> None: # FIXME could we assert the value in entrance? """ Set the underline value. Underline must be `single`, `thick`, `double` or `None`. @@ -1551,7 +1554,7 @@ def underline(self, value: str): self._dummyContext.underline(value) self._addInstruction("underline", value) - def strikethrough(self, value: str): + def strikethrough(self, value: str | None) -> None: # FIXME could we assert the value in entrance? """ Set the strikethrough value. Underline must be `single`, `thick`, `double` or `None`. @@ -1566,7 +1569,7 @@ def strikethrough(self, value: str): self._dummyContext.strikethrough(value) self._addInstruction("strikethrough", value) - def url(self, value: str): + def url(self, value: str) -> None: """ Set the url value for text. @@ -1579,7 +1582,7 @@ def url(self, value: str): self._dummyContext.url(value) self._addInstruction("url", value) - def hyphenation(self, value: bool): + def hyphenation(self, value: bool) -> None: """ Set hyphenation, `True` or `False`. @@ -1597,7 +1600,7 @@ def hyphenation(self, value: bool): self._checkLanguageHyphenation() self._addInstruction("hyphenation", value) - def tabs(self, *tabs: tuple[float, str]): + def tabs(self, *tabs: tuple[float, str]) -> None: r""" Set tabs, tuples of (`float`, `alignment`) Aligment can be `"left"`, `"center"`, `"right"` or any other character. @@ -1624,7 +1627,7 @@ def tabs(self, *tabs: tuple[float, str]): self._dummyContext.tabs(*tabs) self._addInstruction("tabs", *tabs) - def language(self, language): + def language(self, language) -> None: """ Set the preferred language as language tag or None to use the default language. A language tag might be a [iso639-2 or iso639-1](https://www.loc.gov/standards/iso639-2/php/English_list.php) @@ -1674,7 +1677,9 @@ def _checkLanguageHyphenation(self): if not CoreText.CFStringIsHyphenationAvailableForLocale(locale): warnings.warn(f"Language '{language}' has no hyphenation available.") - def writingDirection(self, direction: str | None): + def writingDirection( + self, direction: str | None + ) -> None: # FIXME could we assert the value in entrance? or give a warning? """ Set the writing direction: `None`, `'LTR'` or `'RTL'`. @@ -1734,7 +1739,7 @@ def listOpenTypeFeatures(self, fontNameOrPath: SomePath | None = None) -> list[s listOpenTypeFeatures.__doc__ = FormattedString.listOpenTypeFeatures.__doc__ - def fontVariations(self, *args: None, **axes: float | bool): + def fontVariations(self, *args: None, **axes: float) -> dict[str, float]: # FIXME why was bool there? also, why *args? """ Pick a variation by axes values. @@ -1766,7 +1771,7 @@ def listFontVariations(self, fontNameOrPath: SomePath | None = None) -> dict[str listFontVariations.__doc__ = FormattedString.listFontVariations.__doc__ - def fontNamedInstance(self, name: str, fontNameOrPath: SomePath | None = None): + def fontNamedInstance(self, name: str, fontNameOrPath: SomePath | None = None) -> None: """ Set a font with `name` of a named instance. The `name` of the named instance must be listed in `listNamedInstances()`, @@ -1798,7 +1803,7 @@ def textProperties(self) -> dict[str, Any]: # drawing text - def text(self, txt: FormattedString | str, position: Point, align: str | None = None): + def text(self, txt: FormattedString | str, position: Point, align: str | None = None) -> None: """ Draw a text at a provided position. @@ -1830,7 +1835,12 @@ def text(self, txt: FormattedString | str, position: Point, align: str | None = subTxt.copyContextProperties(txt) self.textBox(subTxt, box, align=align) - def textOverflow(self, txt: FormattedString | str, box: BoundingBox, align: str | None = None): + def textOverflow( + self, + txt: FormattedString | str, + box: BoundingBox | BezierPath, + align: str | None = None, + ) -> FormattedString | str | None: """ Returns the overflowed text without drawing the text. @@ -1854,7 +1864,9 @@ def textOverflow(self, txt: FormattedString | str, box: BoundingBox, align: str raise DrawBotError("align must be %s" % (", ".join(self._dummyContext._textAlignMap.keys()))) return self._dummyContext.clippedText(txt, box, align) - def textBox(self, txt: FormattedString | str, box: BoundingBox, align: str | None = None): + def textBox( + self, txt: FormattedString | str, box: BoundingBox, align: str | None = None + ) -> str | FormattedString: # FIXME is this correct? """ Draw a text in a provided rectangle. @@ -1992,7 +2004,9 @@ def textBox(self, txt: FormattedString | str, box: BoundingBox, align: str | Non self._addInstruction("textBox", txt, box, align) return self._dummyContext.clippedText(txt, box, align) - def textBoxBaselines(self, txt: FormattedString | str, box: BoundingBox, align: str | None = None): + def textBoxBaselines( + self, txt: FormattedString | str, box: BoundingBox, align: str | None = None + ) -> list[tuple[float, float]]: """ Returns a list of `x, y` coordinates indicating the start of each line @@ -2013,7 +2027,10 @@ def textBoxBaselines(self, txt: FormattedString | str, box: BoundingBox, align: origins = CoreText.CTFrameGetLineOrigins(box, (0, len(ctLines)), None) return [(x + o.x, y + o.y) for o in origins] - def textBoxCharacterBounds(self, txt: FormattedString | str, box: BoundingBox, align: str | None = None): + # FIXME align is not used + def textBoxCharacterBounds( + self, txt: FormattedString | str, box: BoundingBox, align: str | None = None + ) -> list[tuple[BoundingBox | BezierPath, float, FormattedString | str]]: """ Returns a list of typesetted bounding boxes `((x, y, w, h), baseLineOffset, formattedSubString)`. @@ -2057,7 +2074,7 @@ def image( position: Point, alpha: float = 1, pageNumber: int | None = None, - ): + ) -> None: """ Add an image from a `path` with an `offset` and an `alpha` value. This accepts most common file types like pdf, jpg, png, tiff and gif. `NSImage` objects are accepted too. @@ -2203,9 +2220,16 @@ def imagePixelColor( if color is None: return None color = color.colorUsingColorSpaceName_("NSCalibratedRGBColorSpace") - return color.redComponent(), color.greenComponent(), color.blueComponent(), color.alphaComponent() + return ( + color.redComponent(), + color.greenComponent(), + color.blueComponent(), + color.alphaComponent(), + ) - def imageResolution(self, path: SomePath | AppKit.NSImage) -> int: + def imageResolution( + self, path: SomePath | AppKit.NSImage + ) -> int: # FIXME how can it be an integer with that kind of arithmetic operation? """ Return the image resolution for a given image. Supports pdf, jpg, png, tiff and gif file formats. `NSImage` objects are supported too. """ @@ -2257,7 +2281,7 @@ def numberOfPages(self, path: SomePath) -> int | None: # mov - def frameDuration(self, seconds: float): + def frameDuration(self, seconds: float) -> None: """ When exporting to `mov` or `gif` each frame can have duration set in `seconds`. @@ -2378,7 +2402,7 @@ def textSize( align: str | None = None, width: float | None = None, height: float | None = None, - ): + ) -> tuple[float, float]: """ Returns the size of a text with the current settings, like `font`, `fontSize` and `lineHeight` as a tuple (width, height). @@ -2458,7 +2482,7 @@ def installFont(self, path: SomePath) -> str: warnings.warn("install font: %s" % error) return psName - def uninstallFont(self, path: SomePath): + def uninstallFont(self, path: SomePath) -> None: """ Uninstall a font with a given path. @@ -2549,7 +2573,7 @@ def fontLineHeight(self) -> float: """ return self._dummyContext._state.text.fontLineHeight() - def Variable(self, variables, workSpace, continuous=True): + def Variable(self, variables, workSpace, continuous=True) -> None: """ Build small UI for variables in a script. From 0f522e03ff58e47c3b123e851b3eb3d18c02f727 Mon Sep 17 00:00:00 2001 From: Roberto Arista Date: Thu, 8 May 2025 17:38:29 +0200 Subject: [PATCH 02/29] fix annotations (with note) --- drawBot/drawBotDrawingTools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drawBot/drawBotDrawingTools.py b/drawBot/drawBotDrawingTools.py index 2476f578..af427475 100644 --- a/drawBot/drawBotDrawingTools.py +++ b/drawBot/drawBotDrawingTools.py @@ -388,7 +388,7 @@ def pages(self) -> tuple[DrawBotPage, ...]: break return tuple(DrawBotPage(instructionSet) for instructionSet in instructions) - def saveImage(self, path: SomePath, *args, **options: dict[str, Any]): + def saveImage(self, path: SomePath, *args: Any, **options: Any): # FIXME how could we annotate this one? """ Save or export the canvas to a specified format. The `path` argument is a single destination path to save the current drawing actions. From 8635b994c9fe08930b1777d0e7e2c7db287d2ae7 Mon Sep 17 00:00:00 2001 From: Roberto Arista Date: Thu, 8 May 2025 17:38:39 +0200 Subject: [PATCH 03/29] notes --- drawBot/drawBotDrawingTools.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drawBot/drawBotDrawingTools.py b/drawBot/drawBotDrawingTools.py index af427475..56ab1741 100644 --- a/drawBot/drawBotDrawingTools.py +++ b/drawBot/drawBotDrawingTools.py @@ -496,7 +496,7 @@ def printImage(self, pdf=None) -> None: else: context.printImage(pdf) - def pdfImage(self): + def pdfImage(self): # FIXME how could we annotate this? """ Return the image as a pdf document object. """ @@ -1698,7 +1698,7 @@ def writingDirection( self._dummyContext.writingDirection(direction) self._addInstruction("writingDirection", direction) - def openTypeFeatures(self, *args: bool | None, **features: bool) -> dict[str, bool]: + def openTypeFeatures(self, *args: bool | None, **features: bool) -> dict[str, bool]: # FIXME I am sure we discussed this already, but why do we need args here? From the example is not evident... """ Enable OpenType features. From 59f950e111c98901d316a4c3a838a571885fbd3a Mon Sep 17 00:00:00 2001 From: Roberto Arista Date: Thu, 8 May 2025 17:40:16 +0200 Subject: [PATCH 04/29] ruff --- drawBot/drawBotDrawingTools.py | 42 +++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/drawBot/drawBotDrawingTools.py b/drawBot/drawBotDrawingTools.py index 56ab1741..2e17f939 100644 --- a/drawBot/drawBotDrawingTools.py +++ b/drawBot/drawBotDrawingTools.py @@ -1173,7 +1173,15 @@ def radialGradient( rect(10, 10, 980, 980) """ self._requiresNewFirstPage = True - self._addInstruction("radialGradient", startPoint, endPoint, colors, locations, startRadius, endRadius) + self._addInstruction( + "radialGradient", + startPoint, + endPoint, + colors, + locations, + startRadius, + endRadius, + ) def cmykRadialGradient( self, @@ -1211,7 +1219,15 @@ def cmykRadialGradient( rect(10, 10, 980, 980) """ self._requiresNewFirstPage = True - self._addInstruction("cmykRadialGradient", startPoint, endPoint, colors, locations, startRadius, endRadius) + self._addInstruction( + "cmykRadialGradient", + startPoint, + endPoint, + colors, + locations, + startRadius, + endRadius, + ) # path drawing behavoir @@ -1698,7 +1714,11 @@ def writingDirection( self._dummyContext.writingDirection(direction) self._addInstruction("writingDirection", direction) - def openTypeFeatures(self, *args: bool | None, **features: bool) -> dict[str, bool]: # FIXME I am sure we discussed this already, but why do we need args here? From the example is not evident... + def openTypeFeatures( + self, *args: bool | None, **features: bool + ) -> dict[ + str, bool + ]: # FIXME I am sure we discussed this already, but why do we need args here? From the example is not evident... """ Enable OpenType features. @@ -1739,7 +1759,9 @@ def listOpenTypeFeatures(self, fontNameOrPath: SomePath | None = None) -> list[s listOpenTypeFeatures.__doc__ = FormattedString.listOpenTypeFeatures.__doc__ - def fontVariations(self, *args: None, **axes: float) -> dict[str, float]: # FIXME why was bool there? also, why *args? + def fontVariations( + self, *args: None, **axes: float + ) -> dict[str, float]: # FIXME why was bool there? also, why *args? """ Pick a variation by axes values. @@ -1829,7 +1851,10 @@ def text(self, txt: FormattedString | str, position: Point, align: str | None = raise DrawBotError("align must be left, right, center") attributedString = self._dummyContext.attributedString(txt, align=align) for subTxt, box in makeTextBoxes( - attributedString, (x, y), align=align, plainText=not isinstance(txt, FormattedString) + attributedString, + (x, y), + align=align, + plainText=not isinstance(txt, FormattedString), ): if isinstance(txt, FormattedString): subTxt.copyContextProperties(txt) @@ -2060,7 +2085,12 @@ def textBoxCharacterBounds( runW, runH, ascent, descent = CoreText.CTRunGetTypographicBounds(ctRun, (0, 0), None, None, None) bounds.append( CharactersBounds( - (x + originX + runPos.x, y + originY + runPos.y - ascent, runW, runH + ascent), + ( + x + originX + runPos.x, + y + originY + runPos.y - ascent, + runW, + runH + ascent, + ), ascent, txt[runRange.location : runRange.location + runRange.length], ) From fd1c1fec92a14f643d3e4edd8819127d83ace829 Mon Sep 17 00:00:00 2001 From: Roberto Arista Date: Thu, 8 May 2025 17:55:01 +0200 Subject: [PATCH 05/29] improve hint --- drawBot/drawBotDrawingTools.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drawBot/drawBotDrawingTools.py b/drawBot/drawBotDrawingTools.py index 2e17f939..89282918 100644 --- a/drawBot/drawBotDrawingTools.py +++ b/drawBot/drawBotDrawingTools.py @@ -1890,8 +1890,8 @@ def textOverflow( return self._dummyContext.clippedText(txt, box, align) def textBox( - self, txt: FormattedString | str, box: BoundingBox, align: str | None = None - ) -> str | FormattedString: # FIXME is this correct? + self, txt: FormattedString | str, box: BoundingBox, align: str | None = None, + ) -> str | FormattedString | None: """ Draw a text in a provided rectangle. From ce535a65331b145c6185f7892b17de3d0dcde403 Mon Sep 17 00:00:00 2001 From: Roberto Arista Date: Thu, 8 May 2025 17:57:43 +0200 Subject: [PATCH 06/29] avoid issue with circular import --- drawBot/drawBotDrawingTools.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drawBot/drawBotDrawingTools.py b/drawBot/drawBotDrawingTools.py index 89282918..d7cdd7e7 100644 --- a/drawBot/drawBotDrawingTools.py +++ b/drawBot/drawBotDrawingTools.py @@ -8,7 +8,6 @@ import AppKit # type: ignore import CoreText # type: ignore import Quartz # type: ignore -from .drawBotPageDrawingTools import DrawBotPage from .aliases import ( BoundingBox, CMYKColor, @@ -29,6 +28,7 @@ getNSFontFromNameOrPath, makeTextBoxes, ) +from typing import TYPE_CHECKING from .context.dummyContext import DummyContext from .context.tools import drawBotbuiltins, gifTools from .context.tools.imageObject import ImageObject @@ -44,6 +44,8 @@ warnings, ) +if TYPE_CHECKING: + from .drawBotPageDrawingTools import DrawBotPage def _getmodulecontents(module, names=None): d = {} @@ -338,7 +340,8 @@ def newPage(self, width: str | float | None = None, height: float | None = None) self._dummyContext = DummyContext() self._addInstruction("newPage", width, height) - def pages(self) -> tuple[DrawBotPage, ...]: + + def pages(self) -> tuple["DrawBotPage", ...]: """ Return all pages. @@ -380,6 +383,8 @@ def pages(self) -> tuple[DrawBotPage, ...]: # draw an oval in each of them oval(110, 10, 30, 30) """ + from .drawBotPageDrawingTools import DrawBotPage + instructions = [] for instructionSet in self._instructionsStack: for callback, _, _ in instructionSet: From 4f5b82600e1d59a48f3544065bb4c013684355b6 Mon Sep 17 00:00:00 2001 From: Roberto Arista Date: Fri, 9 May 2025 09:47:01 +0200 Subject: [PATCH 07/29] defer evalutation of the annotations --- drawBot/drawBotDrawingTools.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drawBot/drawBotDrawingTools.py b/drawBot/drawBotDrawingTools.py index d7cdd7e7..f1f71130 100644 --- a/drawBot/drawBotDrawingTools.py +++ b/drawBot/drawBotDrawingTools.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import math import os import random @@ -340,8 +342,7 @@ def newPage(self, width: str | float | None = None, height: float | None = None) self._dummyContext = DummyContext() self._addInstruction("newPage", width, height) - - def pages(self) -> tuple["DrawBotPage", ...]: + def pages(self) -> tuple[DrawBotPage, ...]: """ Return all pages. From 6cf18caa45224a46e5ad0567470866a3e6feed04 Mon Sep 17 00:00:00 2001 From: Roberto Arista Date: Fri, 9 May 2025 09:47:09 +0200 Subject: [PATCH 08/29] sort imports --- drawBot/drawBotDrawingTools.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drawBot/drawBotDrawingTools.py b/drawBot/drawBotDrawingTools.py index f1f71130..f012b2e7 100644 --- a/drawBot/drawBotDrawingTools.py +++ b/drawBot/drawBotDrawingTools.py @@ -5,11 +5,12 @@ import random from collections import namedtuple from contextlib import contextmanager -from typing import Any +from typing import TYPE_CHECKING, Any import AppKit # type: ignore import CoreText # type: ignore import Quartz # type: ignore + from .aliases import ( BoundingBox, CMYKColor, @@ -30,7 +31,6 @@ getNSFontFromNameOrPath, makeTextBoxes, ) -from typing import TYPE_CHECKING from .context.dummyContext import DummyContext from .context.tools import drawBotbuiltins, gifTools from .context.tools.imageObject import ImageObject From fd607c73934cf85a84ee5a822e975f124ba7ed70 Mon Sep 17 00:00:00 2001 From: Roberto Arista Date: Fri, 9 May 2025 09:47:25 +0200 Subject: [PATCH 09/29] improve hints --- drawBot/drawBotDrawingTools.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drawBot/drawBotDrawingTools.py b/drawBot/drawBotDrawingTools.py index f012b2e7..bbab4d8c 100644 --- a/drawBot/drawBotDrawingTools.py +++ b/drawBot/drawBotDrawingTools.py @@ -394,7 +394,9 @@ def pages(self) -> tuple[DrawBotPage, ...]: break return tuple(DrawBotPage(instructionSet) for instructionSet in instructions) - def saveImage(self, path: SomePath, *args: Any, **options: Any): # FIXME how could we annotate this one? + def saveImage( + self, path: SomePath, *args: Any, **options: Any + ) -> list[AppKit.NSImage | PIL.ImageFile.ImageFile] | None: """ Save or export the canvas to a specified format. The `path` argument is a single destination path to save the current drawing actions. @@ -502,7 +504,7 @@ def printImage(self, pdf=None) -> None: else: context.printImage(pdf) - def pdfImage(self): # FIXME how could we annotate this? + def pdfImage(self) -> Quartz.PDFDocument: """ Return the image as a pdf document object. """ @@ -2263,9 +2265,7 @@ def imagePixelColor( color.alphaComponent(), ) - def imageResolution( - self, path: SomePath | AppKit.NSImage - ) -> int: # FIXME how can it be an integer with that kind of arithmetic operation? + def imageResolution(self, path: SomePath | AppKit.NSImage) -> float: """ Return the image resolution for a given image. Supports pdf, jpg, png, tiff and gif file formats. `NSImage` objects are supported too. """ From 74cf1bcaf4d74e62c018b3b458324a3bdfbcfa39 Mon Sep 17 00:00:00 2001 From: Roberto Arista Date: Fri, 9 May 2025 09:47:29 +0200 Subject: [PATCH 10/29] format --- drawBot/drawBotDrawingTools.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drawBot/drawBotDrawingTools.py b/drawBot/drawBotDrawingTools.py index bbab4d8c..37f0191b 100644 --- a/drawBot/drawBotDrawingTools.py +++ b/drawBot/drawBotDrawingTools.py @@ -49,6 +49,7 @@ if TYPE_CHECKING: from .drawBotPageDrawingTools import DrawBotPage + def _getmodulecontents(module, names=None): d = {} if names is None: @@ -1898,7 +1899,10 @@ def textOverflow( return self._dummyContext.clippedText(txt, box, align) def textBox( - self, txt: FormattedString | str, box: BoundingBox, align: str | None = None, + self, + txt: FormattedString | str, + box: BoundingBox, + align: str | None = None, ) -> str | FormattedString | None: """ Draw a text in a provided rectangle. From 659c70c10407822684d82b54688f4d47210f16a0 Mon Sep 17 00:00:00 2001 From: Roberto Arista Date: Fri, 9 May 2025 10:00:47 +0200 Subject: [PATCH 11/29] add `None` --- drawBot/drawBotDrawingTools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drawBot/drawBotDrawingTools.py b/drawBot/drawBotDrawingTools.py index 37f0191b..73835d40 100644 --- a/drawBot/drawBotDrawingTools.py +++ b/drawBot/drawBotDrawingTools.py @@ -505,7 +505,7 @@ def printImage(self, pdf=None) -> None: else: context.printImage(pdf) - def pdfImage(self) -> Quartz.PDFDocument: + def pdfImage(self) -> Quartz.PDFDocument | None: """ Return the image as a pdf document object. """ From 60f54304827bff8fb22ae4892ee8a37f7bab85d7 Mon Sep 17 00:00:00 2001 From: Roberto Arista Date: Fri, 9 May 2025 10:10:42 +0200 Subject: [PATCH 12/29] Add `Literal` hints methods affected: - `lineCap` - `underline` - `strikethrough` - `writingDirection` - `text` - `textBox` - `textBoxBaselines` --- drawBot/drawBotDrawingTools.py | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/drawBot/drawBotDrawingTools.py b/drawBot/drawBotDrawingTools.py index 73835d40..631d28d8 100644 --- a/drawBot/drawBotDrawingTools.py +++ b/drawBot/drawBotDrawingTools.py @@ -5,7 +5,7 @@ import random from collections import namedtuple from contextlib import contextmanager -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING, Any, Literal import AppKit # type: ignore import CoreText # type: ignore @@ -1293,7 +1293,7 @@ def miterLimit(self, value: float) -> None: self._requiresNewFirstPage = True self._addInstruction("miterLimit", value) - def lineJoin(self, value: str): + def lineJoin(self, value: Literal["miter", "round", "bevel"]): """ Set a line join. @@ -1336,7 +1336,7 @@ def lineJoin(self, value: str): self._requiresNewFirstPage = True self._addInstruction("lineJoin", value) - def lineCap(self, value: str): + def lineCap(self, value: Literal["butt", "square", "round"]): """ Set a line cap. @@ -1565,7 +1565,7 @@ def baselineShift(self, value) -> None: self._dummyContext.baselineShift(value) self._addInstruction("baselineShift", value) - def underline(self, value: str | None) -> None: # FIXME could we assert the value in entrance? + def underline(self, value: Literal["single", "thick", "double"] | None) -> None: """ Set the underline value. Underline must be `single`, `thick`, `double` or `None`. @@ -1579,7 +1579,7 @@ def underline(self, value: str | None) -> None: # FIXME could we assert the val self._dummyContext.underline(value) self._addInstruction("underline", value) - def strikethrough(self, value: str | None) -> None: # FIXME could we assert the value in entrance? + def strikethrough(self, value: Literal["single", "thick", "double"] | None) -> None: """ Set the strikethrough value. Underline must be `single`, `thick`, `double` or `None`. @@ -1702,9 +1702,7 @@ def _checkLanguageHyphenation(self): if not CoreText.CFStringIsHyphenationAvailableForLocale(locale): warnings.warn(f"Language '{language}' has no hyphenation available.") - def writingDirection( - self, direction: str | None - ) -> None: # FIXME could we assert the value in entrance? or give a warning? + def writingDirection(self, direction: Literal["LTR", "RTL"] | None) -> None: """ Set the writing direction: `None`, `'LTR'` or `'RTL'`. @@ -1834,7 +1832,12 @@ def textProperties(self) -> dict[str, Any]: # drawing text - def text(self, txt: FormattedString | str, position: Point, align: str | None = None) -> None: + def text( + self, + txt: FormattedString | str, + position: Point, + align: Literal["left", "center", "right"] | None = None, + ) -> None: """ Draw a text at a provided position. @@ -1873,7 +1876,7 @@ def textOverflow( self, txt: FormattedString | str, box: BoundingBox | BezierPath, - align: str | None = None, + align: Literal["left", "center", "right", "justified"] | None = None, ) -> FormattedString | str | None: """ Returns the overflowed text without drawing the text. @@ -1902,7 +1905,7 @@ def textBox( self, txt: FormattedString | str, box: BoundingBox, - align: str | None = None, + align: Literal["left", "center", "right", "justified"] | None = None, ) -> str | FormattedString | None: """ Draw a text in a provided rectangle. @@ -2042,7 +2045,10 @@ def textBox( return self._dummyContext.clippedText(txt, box, align) def textBoxBaselines( - self, txt: FormattedString | str, box: BoundingBox, align: str | None = None + self, + txt: FormattedString | str, + box: BoundingBox, + align: Literal["left", "center", "right", "justified"] | None = None, ) -> list[tuple[float, float]]: """ Returns a list of `x, y` coordinates From 14f9c7ce3b3d2a5dea5567613fdbf2dbec4bccc4 Mon Sep 17 00:00:00 2001 From: Roberto Arista Date: Mon, 19 May 2025 15:55:21 +0200 Subject: [PATCH 13/29] improve hints --- drawBot/drawBotDrawingTools.py | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drawBot/drawBotDrawingTools.py b/drawBot/drawBotDrawingTools.py index 631d28d8..1d83d0f9 100644 --- a/drawBot/drawBotDrawingTools.py +++ b/drawBot/drawBotDrawingTools.py @@ -395,9 +395,7 @@ def pages(self) -> tuple[DrawBotPage, ...]: break return tuple(DrawBotPage(instructionSet) for instructionSet in instructions) - def saveImage( - self, path: SomePath, *args: Any, **options: Any - ) -> list[AppKit.NSImage | PIL.ImageFile.ImageFile] | None: + def saveImage(self, path: SomePath, *args: Any, **options: Any): """ Save or export the canvas to a specified format. The `path` argument is a single destination path to save the current drawing actions. @@ -1721,11 +1719,7 @@ def writingDirection(self, direction: Literal["LTR", "RTL"] | None) -> None: self._dummyContext.writingDirection(direction) self._addInstruction("writingDirection", direction) - def openTypeFeatures( - self, *args: bool | None, **features: bool - ) -> dict[ - str, bool - ]: # FIXME I am sure we discussed this already, but why do we need args here? From the example is not evident... + def openTypeFeatures(self, *args: bool | None, **features: bool) -> dict[str, bool]: """ Enable OpenType features. @@ -2070,7 +2064,6 @@ def textBoxBaselines( origins = CoreText.CTFrameGetLineOrigins(box, (0, len(ctLines)), None) return [(x + o.x, y + o.y) for o in origins] - # FIXME align is not used def textBoxCharacterBounds( self, txt: FormattedString | str, box: BoundingBox, align: str | None = None ) -> list[tuple[BoundingBox | BezierPath, float, FormattedString | str]]: @@ -2087,7 +2080,7 @@ def textBoxCharacterBounds( CharactersBounds = namedtuple("CharactersBounds", ["bounds", "baselineOffset", "formattedSubString"]) - bounds = list() + bounds = list[tuple[BoundingBox | BezierPath, float, FormattedString | str]]() path, (x, y) = self._dummyContext._getPathForFrameSetter(box) attrString = self._dummyContext.attributedString(txt) setter = CoreText.CTFramesetterCreateWithAttributedString(attrString) From 79400aca86d298e00de77c679ca2933ec1b58abd Mon Sep 17 00:00:00 2001 From: Roberto Arista Date: Mon, 19 May 2025 15:57:52 +0200 Subject: [PATCH 14/29] we can import PIL, so we can get this one back --- drawBot/drawBotDrawingTools.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drawBot/drawBotDrawingTools.py b/drawBot/drawBotDrawingTools.py index 1d83d0f9..c24130b2 100644 --- a/drawBot/drawBotDrawingTools.py +++ b/drawBot/drawBotDrawingTools.py @@ -9,6 +9,7 @@ import AppKit # type: ignore import CoreText # type: ignore +import PIL # type: ignore import Quartz # type: ignore from .aliases import ( @@ -395,7 +396,9 @@ def pages(self) -> tuple[DrawBotPage, ...]: break return tuple(DrawBotPage(instructionSet) for instructionSet in instructions) - def saveImage(self, path: SomePath, *args: Any, **options: Any): + def saveImage( + self, path: SomePath, *args: Any, **options: Any + ) -> list[AppKit.NSImage | PIL.ImageFile.ImageFile] | None: """ Save or export the canvas to a specified format. The `path` argument is a single destination path to save the current drawing actions. From 07f31625708f2a01de9328a8dd18b73512380cbd Mon Sep 17 00:00:00 2001 From: Roberto Arista Date: Thu, 8 May 2025 17:57:43 +0200 Subject: [PATCH 15/29] avoid issue with circular import --- drawBot/drawBotDrawingTools.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drawBot/drawBotDrawingTools.py b/drawBot/drawBotDrawingTools.py index 9a9773d3..129df6b8 100644 --- a/drawBot/drawBotDrawingTools.py +++ b/drawBot/drawBotDrawingTools.py @@ -33,6 +33,7 @@ makeTextBoxes, newFramesetterWithAttributedString, ) +from typing import TYPE_CHECKING from .context.dummyContext import DummyContext from .context.tools import drawBotbuiltins, gifTools from .context.tools.imageObject import ImageObject @@ -345,7 +346,8 @@ def newPage(self, width: str | float | None = None, height: float | None = None) self._dummyContext = DummyContext() self._addInstruction("newPage", width, height) - def pages(self) -> tuple[DrawBotPage, ...]: + + def pages(self) -> tuple["DrawBotPage", ...]: """ Return all pages. From 9e1daeb9bf909548af448a5c28bd3b6d1ad60516 Mon Sep 17 00:00:00 2001 From: Roberto Arista Date: Fri, 9 May 2025 09:47:09 +0200 Subject: [PATCH 16/29] sort imports --- drawBot/drawBotDrawingTools.py | 1 - 1 file changed, 1 deletion(-) diff --git a/drawBot/drawBotDrawingTools.py b/drawBot/drawBotDrawingTools.py index 129df6b8..200f495b 100644 --- a/drawBot/drawBotDrawingTools.py +++ b/drawBot/drawBotDrawingTools.py @@ -33,7 +33,6 @@ makeTextBoxes, newFramesetterWithAttributedString, ) -from typing import TYPE_CHECKING from .context.dummyContext import DummyContext from .context.tools import drawBotbuiltins, gifTools from .context.tools.imageObject import ImageObject From 8fa14613a5ea142831f40ca1bb5fb02d407757cf Mon Sep 17 00:00:00 2001 From: Roberto Arista Date: Mon, 19 May 2025 15:55:21 +0200 Subject: [PATCH 17/29] improve hints --- drawBot/drawBotDrawingTools.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drawBot/drawBotDrawingTools.py b/drawBot/drawBotDrawingTools.py index 200f495b..afdff638 100644 --- a/drawBot/drawBotDrawingTools.py +++ b/drawBot/drawBotDrawingTools.py @@ -398,9 +398,7 @@ def pages(self) -> tuple["DrawBotPage", ...]: break return tuple(DrawBotPage(instructionSet) for instructionSet in instructions) - def saveImage( - self, path: SomePath, *args: Any, **options: Any - ) -> list[AppKit.NSImage | PIL.ImageFile.ImageFile] | None: + def saveImage(self, path: SomePath, *args: Any, **options: Any): """ Save or export the canvas to a specified format. The `path` argument is a single destination path to save the current drawing actions. From be052521c654e7f439cd601698c35f445c88e14f Mon Sep 17 00:00:00 2001 From: Roberto Arista Date: Fri, 10 Apr 2026 09:34:10 +0200 Subject: [PATCH 18/29] improve docs --- drawBot/drawBotDrawingTools.py | 42 +++++++++++++++++----------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/drawBot/drawBotDrawingTools.py b/drawBot/drawBotDrawingTools.py index afdff638..07552d69 100644 --- a/drawBot/drawBotDrawingTools.py +++ b/drawBot/drawBotDrawingTools.py @@ -873,7 +873,7 @@ def fill( ) -> None: """ Sets the fill color with a `red`, `green`, `blue` and `alpha` value. - Each argument must a value float between 0 and 1. + Each argument must be a value float between 0 and 1. .. downloadcode:: fill.py @@ -913,7 +913,7 @@ def stroke( ) -> None: """ Sets the stroke color with a `red`, `green`, `blue` and `alpha` value. - Each argument must a value float between 0 and 1. + Each argument must be a value float between 0 and 1. .. downloadcode:: stroke.py @@ -1043,7 +1043,7 @@ def shadow( """ Adds a shadow with an `offset` (x, y), `blur` and a `color`. The `color` argument must be a tuple similarly as `fill`. - The `offset`and `blur` argument will be drawn independent of the current context transformations. + The `offset` and `blur` argument will be drawn independent of the current context transformations. .. downloadcode:: shadow.py @@ -1161,7 +1161,7 @@ def radialGradient( * `startPoint` as (x, y) * `endPoint` as (x, y) - * `colors` as a list of colors, described similary as `fill` + * `colors` as a list of colors, described similarly as `fill` * `locations` of each color as a list of floats. (optionally) * `startRadius` radius around the startPoint in degrees (optionally) * `endRadius` radius around the endPoint in degrees (optionally) @@ -1207,7 +1207,7 @@ def cmykRadialGradient( * `startPoint` as (x, y) * `endPoint` as (x, y) - * `colors` as a list of colors, described similary as `cmykFill` + * `colors` as a list of colors, described similarly as `cmykFill` * `locations` of each color as a list of floats. (optionally) * `startRadius` radius around the startPoint in degrees (optionally) * `endRadius` radius around the endPoint in degrees (optionally) @@ -1347,7 +1347,7 @@ def lineCap(self, value: Literal["butt", "square", "round"]): # set stroke color to black stroke(0) - # set a strok width + # set a stroke width strokeWidth(50) # translate the canvas translate(150, 50) @@ -1361,7 +1361,7 @@ def lineCap(self, value: Literal["butt", "square", "round"]): lineCap("square") # draw a line line((0, 200), (0, 800)) - # translate the canvase + # translate the canvas translate(300, 0) # set a line cap style lineCap("round") @@ -1373,8 +1373,8 @@ def lineCap(self, value: Literal["butt", "square", "round"]): def lineDash(self, value: float | None, *values: float, offset: float = 0): """ - Set a line dash with any given amount of lenghts. - Uneven lenghts will have a visible stroke, even lenghts will be invisible. + Set a line dash with any given amount of lengths. + Uneven lengths will have a visible stroke, even lengths will be invisible. optionally an `offset` can be given to set the offset of the first dash. @@ -1382,7 +1382,7 @@ def lineDash(self, value: float | None, *values: float, offset: float = 0): # set stroke color to black stroke(0) - # set a strok width + # set a stroke width strokeWidth(50) # translate the canvas translate(150, 50) @@ -1402,7 +1402,7 @@ def lineDash(self, value: float | None, *values: float, offset: float = 0): lineDash(2, 10, 5, 5, offset=2) # draw a line line((0, 200), (0, 800)) - # translate the canvase + # translate the canvas translate(200, 0) # reset the line dash lineDash(None) @@ -1583,7 +1583,7 @@ def underline(self, value: Literal["single", "thick", "double"] | None) -> None: def strikethrough(self, value: Literal["single", "thick", "double"] | None) -> None: """ Set the strikethrough value. - Underline must be `single`, `thick`, `double` or `None`. + Strikethrough must be `single`, `thick`, `double` or `None`. .. downloadcode:: strikethrough.py @@ -1679,7 +1679,7 @@ def language(self, language) -> None: language("nl") # shift up a bit translate(500, 0) - # darw the text again with a language set + # draw the text again with a language set textBox(word, box) """ self._dummyContext.language(language) @@ -1800,7 +1800,7 @@ def listFontVariations(self, fontNameOrPath: SomePath | None = None) -> dict[str def fontNamedInstance(self, name: str, fontNameOrPath: SomePath | None = None) -> None: """ Set a font with `name` of a named instance. - The `name` of the named instance must be listed in `listNamedInstances()`, + The `name` of the named instance must be listed in `listNamedInstances()`. Optionally a `fontNameOrPath` can be given. If a font path is given that `fontNameOrPath` will be set. @@ -1924,12 +1924,12 @@ def textBox( fill(1, 0, 0) # draw a rectangle with variables from above rect(x, y, w, h) - # set a diferent fill + # set a different fill fill(1) # set a font size fontSize(200) # draw text in a text box - # with varibales from above + # with variables from above overflow = textBox("hallo, this text is a bit to long", (x, y, w, h), align="center") # a text box returns text overflow @@ -2120,12 +2120,12 @@ def image( pageNumber: int | None = None, ) -> None: """ - Add an image from a `path` with an `offset` and an `alpha` value. + Add an image from a `path` with a `position` and an `alpha` value. This accepts most common file types like pdf, jpg, png, tiff and gif. `NSImage` objects are accepted too. Optionally an `alpha` can be provided, which is a value between 0 and 1. - Optionally a `pageNumber` can be provided when the path referes to a multi page pdf file. + Optionally a `pageNumber` can be provided when the path refers to a multi page pdf file. .. downloadcode:: image.py @@ -2336,7 +2336,7 @@ def frameDuration(self, seconds: float) -> None: fps = 30 # duration of the movie seconds = 3 - # calculate the lenght of a single frame + # calculate the length of a single frame duration = 1 / fps # calculate the amount of frames needed totalFrames = seconds * fps @@ -2450,7 +2450,7 @@ def textSize( like `font`, `fontSize` and `lineHeight` as a tuple (width, height). Optionally a `width` constrain or `height` constrain can be provided - to calculate the lenght or width of text with the given constrain. + to calculate the length or width of text with the given constrain. """ if not isinstance(txt, (str, FormattedString)): raise TypeError("expected 'str' or 'FormattedString', got '%s'" % type(txt).__name__) @@ -2485,7 +2485,7 @@ def installFont(self, path: SomePath) -> str: The postscript font name can be used to set the font as the active font. Fonts are installed only for the current process. - Fonts will not be accesible outside the scope of drawBot. + Fonts will not be accessible outside the scope of drawBot. All installed fonts will automatically be uninstalled when the script is done. From 46420f5b0a31e15fde402e50a7ff00bad250e3f8 Mon Sep 17 00:00:00 2001 From: Roberto Arista Date: Fri, 10 Apr 2026 09:42:56 +0200 Subject: [PATCH 19/29] improve hints --- drawBot/context/baseContext.py | 68 ++++++++++++++-------------- drawBot/context/tools/imageObject.py | 10 ++-- drawBot/drawBotDrawingTools.py | 58 ++++++++++++------------ 3 files changed, 66 insertions(+), 70 deletions(-) diff --git a/drawBot/context/baseContext.py b/drawBot/context/baseContext.py index 63d9d52f..d5a377cd 100644 --- a/drawBot/context/baseContext.py +++ b/drawBot/context/baseContext.py @@ -264,13 +264,13 @@ def _curveToOne(self, pt1, pt2, pt3): """ self._path.curveToPoint_controlPoint1_controlPoint2_(pt3, pt1, pt2) - def closePath(self): + def closePath(self) -> None: """ Close the path. """ self._path.closePath() - def beginPath(self, identifier=None): + def beginPath(self, identifier: str | None = None) -> None: """ Begin using the path as a so called point pen and start a new subpath. """ @@ -285,9 +285,9 @@ def addPoint( segmentType: str | None = None, smooth: bool = False, name: str | None = None, - identifier=None, - **kwargs, - ): + identifier: str | None = None, + **kwargs: Any, + ) -> None: """ Use the path as a point pen and add a point to the current subpath. `beginPath` must have been called prior to adding points with `addPoint` calls. @@ -303,7 +303,7 @@ def addPoint( **kwargs, ) - def endPath(self): + def endPath(self) -> None: """ End the current subpath. Calling this method has two distinct meanings depending on the context: @@ -603,7 +603,7 @@ def controlPointBounds(self) -> BoundingBox | None: (x, y), (w, h) = self._path.controlPointBounds() return x, y, x + w, y + h - def optimizePath(self): + def optimizePath(self) -> None: count = self._path.elementCount() if not count or self._path.elementAtIndex_(count - 1) != AppKit.NSMoveToBezierPathElement: return @@ -630,13 +630,13 @@ def copy(self) -> Self: new.copyContextProperties(self) return new - def reverse(self): + def reverse(self) -> None: """ Reverse the path direction """ self._path = self._path.bezierPathByReversingPath() - def appendPath(self, otherPath: Self): + def appendPath(self, otherPath: Self) -> None: """ Append a path. """ @@ -653,13 +653,13 @@ def __iadd__(self, other: Self) -> Self: # transformations - def translate(self, x: float = 0, y: float = 0): + def translate(self, x: float = 0, y: float = 0) -> None: """ Translate the path with a given offset. """ self.transform((1, 0, 0, 1, x, y)) - def rotate(self, angle: float, center: Point = (0, 0)): + def rotate(self, angle: float, center: Point = (0, 0)) -> None: """ Rotate the path around the `center` point (which is the origin by default) with a given angle in degrees. """ @@ -668,7 +668,7 @@ def rotate(self, angle: float, center: Point = (0, 0)): s = math.sin(angle) self.transform((c, s, -s, c, 0, 0), center) - def scale(self, x: float = 1, y: float | None = None, center: Point = (0, 0)): + def scale(self, x: float = 1, y: float | None = None, center: Point = (0, 0)) -> None: """ Scale the path with a given `x` (horizontal scale) and `y` (vertical scale). @@ -680,7 +680,7 @@ def scale(self, x: float = 1, y: float | None = None, center: Point = (0, 0)): y = x self.transform((x, 0, 0, y, 0, 0), center) - def skew(self, angle1: float, angle2: float = 0, center: Point = (0, 0)): + def skew(self, angle1: float, angle2: float = 0, center: Point = (0, 0)) -> None: """ Skew the path with given `angle1` and `angle2`. @@ -692,7 +692,7 @@ def skew(self, angle1: float, angle2: float = 0, center: Point = (0, 0)): angle2 = math.radians(angle2) self.transform((1, math.tan(angle2), math.tan(angle1), 1, 0, 0), center) - def transform(self, transformMatrix: TransformTuple, center: Point = (0, 0)): + def transform(self, transformMatrix: TransformTuple, center: Point = (0, 0)) -> None: """ Transform a path with a transform matrix (xy, xx, yy, yx, x, y). """ @@ -1638,7 +1638,7 @@ def font( font = getNSFontFromNameOrPath(fontNameOrPath, fontSize or 10, fontNumber) return getFontName(font) - def fontNumber(self, fontNumber: int): + def fontNumber(self, fontNumber: int) -> None: self._fontNumber = fontNumber def fallbackFont(self, fontNameOrPath: SomePath, fontNumber: int = 0) -> str | None: @@ -1656,17 +1656,17 @@ def fallbackFont(self, fontNameOrPath: SomePath, fontNumber: int = 0) -> str | N self._fallbackFontNumber = fontNumber return fontName - def fallbackFontNumber(self, fontNumber: int): + def fallbackFontNumber(self, fontNumber: int) -> None: self._fallbackFontNumber = fontNumber - def fontSize(self, fontSize: float): + def fontSize(self, fontSize: float) -> None: """ Set the font size in points. The default `fontSize` is 10pt. """ self._fontSize = fontSize - def fill(self, r: float | None = None, g: float | None = None, b: float | None = None, alpha: float = 1): + def fill(self, r: float | None = None, g: float | None = None, b: float | None = None, alpha: float = 1) -> None: """ Sets the fill color with a `red`, `green`, `blue` and `alpha` value. Each argument must a value float between 0 and 1. @@ -1678,7 +1678,7 @@ def fill(self, r: float | None = None, g: float | None = None, b: float | None = self._fill = fill self._cmykFill = None - def stroke(self, r: float | None = None, g: float | None = None, b: float | None = None, alpha: float = 1): + def stroke(self, r: float | None = None, g: float | None = None, b: float | None = None, alpha: float = 1) -> None: """ Sets the stroke color with a `red`, `green`, `blue` and `alpha` value. Each argument must a value float between 0 and 1. @@ -1697,7 +1697,7 @@ def cmykFill( y: float | None = None, k: float | None = None, alpha: float = 1, - ): + ) -> None: """ Set a fill using a CMYK color before drawing a shape. This is handy if the file is intended for print. @@ -1730,39 +1730,39 @@ def cmykStroke( self._cmykStroke = cmykStroke self._stroke = None - def strokeWidth(self, strokeWidth: float): + def strokeWidth(self, strokeWidth: float) -> None: """ Sets stroke width. """ self._strokeWidth = strokeWidth - def align(self, align: str): + def align(self, align: str) -> None: """ Sets the text alignment. Possible `align` values are: `left`, `center` and `right`. """ self._align = align - def lineHeight(self, lineHeight: float): + def lineHeight(self, lineHeight: float) -> None: """ Set the line height. """ self._lineHeight = lineHeight - def tracking(self, tracking: float): + def tracking(self, tracking: float) -> None: """ Set the tracking between characters. It adds an absolute number of points between the characters. """ self._tracking = tracking - def baselineShift(self, baselineShift: float): + def baselineShift(self, baselineShift: float) -> None: """ Set the shift of the baseline. """ self._baselineShift = baselineShift - def underline(self, underline: str | None): + def underline(self, underline: str | None) -> None: """ Set the underline value. Underline must be `single`, `thick`, `double` or `None`. @@ -1771,7 +1771,7 @@ def underline(self, underline: str | None): raise DrawBotError("underline must be %s" % (", ".join(sorted(self._textUnderlineMap.keys())))) self._underline = underline - def strikethrough(self, strikethrough: str | None): + def strikethrough(self, strikethrough: str | None) -> None: """ Set the strikethrough value. Strikethrough must be `single`, `thick`, `double` or `None`. @@ -1780,7 +1780,7 @@ def strikethrough(self, strikethrough: str | None): raise DrawBotError("strikethrough must be %s" % (", ".join(sorted(self._textstrikethroughMap.keys())))) self._strikethrough = strikethrough - def url(self, url: str | None): + def url(self, url: str | None) -> None: """ set the url value. url must be a string or `None` @@ -1908,7 +1908,7 @@ def listNamedInstances(self, fontNameOrPath: SomePath | None = None, fontNumber: font = getNSFontFromNameOrPath(fontNameOrPath, 10, fontNumber) return variation.getNamedInstancesForFont(font) - def tabs(self, tab: tuple[float, str] | None, *tabs: tuple[float, str]): + def tabs(self, tab: tuple[float, str] | None, *tabs: tuple[float, str]) -> None: """ Set tabs,tuples of (`float`, `alignment`) Aligment can be `"left"`, `"center"`, `"right"` or any other character. @@ -1932,7 +1932,7 @@ def tabs(self, tab: tuple[float, str] | None, *tabs: tuple[float, str]): combinedTabs.extend(tabs) self._tabs = combinedTabs - def indent(self, indent: float): + def indent(self, indent: float) -> None: """ Set indent of text left of the paragraph. @@ -2005,7 +2005,7 @@ def indent(self, indent: float): """ self._indent = indent - def tailIndent(self, indent: float): + def tailIndent(self, indent: float) -> None: """ Set indent of text right of the paragraph. @@ -2014,19 +2014,19 @@ def tailIndent(self, indent: float): """ self._tailIndent = indent - def firstLineIndent(self, indent: float): + def firstLineIndent(self, indent: float) -> None: """ Set indent of the text only for the first line. """ self._firstLineIndent = indent - def paragraphTopSpacing(self, value: float): + def paragraphTopSpacing(self, value: float) -> None: """ set paragraph spacing at the top. """ self._paragraphTopSpacing = value - def paragraphBottomSpacing(self, value: float): + def paragraphBottomSpacing(self, value: float) -> None: """ set paragraph spacing at the bottom. """ diff --git a/drawBot/context/tools/imageObject.py b/drawBot/context/tools/imageObject.py index 1e3fefca..e71f3caf 100644 --- a/drawBot/context/tools/imageObject.py +++ b/drawBot/context/tools/imageObject.py @@ -1,15 +1,11 @@ -import AppKit # type: ignore -import Quartz # type: ignore -from math import radians import os from math import radians -from typing import Any - -import AppKit from typing import Self +import AppKit # type: ignore +import Quartz # type: ignore + from drawBot.aliases import BoundingBox, Point, RGBAColorTuple, Size, SomePath, TransformTuple -from drawBot.context.baseContext import FormattedString from drawBot.context.imageContext import _makeBitmapImageRep from drawBot.misc import DrawBotError, optimizePath diff --git a/drawBot/drawBotDrawingTools.py b/drawBot/drawBotDrawingTools.py index 07552d69..7e3fd0b9 100644 --- a/drawBot/drawBotDrawingTools.py +++ b/drawBot/drawBotDrawingTools.py @@ -9,21 +9,8 @@ import AppKit # type: ignore import CoreText # type: ignore -import PIL # type: ignore import Quartz # type: ignore -from .aliases import ( - BoundingBox, - CMYKColor, - CMYKColorTuple, - Point, - RGBAColorTuple, - RGBColor, - RGBColorTuple, - Size, - SomePath, - TransformTuple, -) from .context import getContextForFileExt, getContextOptionsDocs, getFileExtensions from .context.baseContext import ( BezierPath, @@ -49,6 +36,20 @@ ) if TYPE_CHECKING: + from collections.abc import Generator + + from .aliases import ( + BoundingBox, + CMYKColor, + CMYKColorTuple, + Point, + RGBAColorTuple, + RGBColor, + RGBColorTuple, + Size, + SomePath, + TransformTuple, + ) from .drawBotPageDrawingTools import DrawBotPage @@ -197,7 +198,7 @@ def endDrawing(self) -> None: gifTools.clearExplodedGifCache() @contextmanager - def drawing(self): + def drawing(self) -> Generator[None, None, None]: """ Reset and clean the drawing stack in a `with` statement. @@ -345,7 +346,6 @@ def newPage(self, width: str | float | None = None, height: float | None = None) self._dummyContext = DummyContext() self._addInstruction("newPage", width, height) - def pages(self) -> tuple["DrawBotPage", ...]: """ Return all pages. @@ -543,7 +543,7 @@ def restore(self) -> None: self._addInstruction("restore") @contextmanager - def savedState(self): + def savedState(self) -> Generator[None, None, None]: """ Save and restore the current graphics state in a `with` statement. @@ -796,7 +796,7 @@ def polygon(self, *points: Point, **kwargs: bool) -> None: # color - def colorSpace(self, colorSpace) -> None: + def colorSpace(self, colorSpace: str | None) -> None: """ Set the color space. Options are `genericRGB`, `adobeRGB1998`, `sRGB`, `genericGray`, `genericGamma22Gray`. @@ -1089,7 +1089,7 @@ def linearGradient( endPoint: Point | None = None, colors: list[RGBColor | RGBColorTuple] | None = None, locations: list[float] | None = None, - ): + ) -> None: """ A linear gradient fill with: @@ -1294,7 +1294,7 @@ def miterLimit(self, value: float) -> None: self._requiresNewFirstPage = True self._addInstruction("miterLimit", value) - def lineJoin(self, value: Literal["miter", "round", "bevel"]): + def lineJoin(self, value: Literal["miter", "round", "bevel"]) -> None: """ Set a line join. @@ -1337,7 +1337,7 @@ def lineJoin(self, value: Literal["miter", "round", "bevel"]): self._requiresNewFirstPage = True self._addInstruction("lineJoin", value) - def lineCap(self, value: Literal["butt", "square", "round"]): + def lineCap(self, value: Literal["butt", "square", "round"]) -> None: """ Set a line cap. @@ -1371,7 +1371,7 @@ def lineCap(self, value: Literal["butt", "square", "round"]): self._requiresNewFirstPage = True self._addInstruction("lineCap", value) - def lineDash(self, value: float | None, *values: float, offset: float = 0): + def lineDash(self, value: float | None, *values: float, offset: float = 0) -> None: """ Set a line dash with any given amount of lengths. Uneven lengths will have a visible stroke, even lengths will be invisible. @@ -1521,7 +1521,7 @@ def fontSize(self, fontSize: float) -> None: self._dummyContext.fontSize(fontSize) self._addInstruction("fontSize", fontSize) - def lineHeight(self, value): + def lineHeight(self, value: float) -> None: """ Set the line height. @@ -1559,7 +1559,7 @@ def tracking(self, value: float) -> None: self._dummyContext.tracking(value) self._addInstruction("tracking", value) - def baselineShift(self, value) -> None: + def baselineShift(self, value: float) -> None: """ Set the shift of the baseline. """ @@ -1653,7 +1653,7 @@ def tabs(self, *tabs: tuple[float, str]) -> None: self._dummyContext.tabs(*tabs) self._addInstruction("tabs", *tabs) - def language(self, language) -> None: + def language(self, language: str | None) -> None: """ Set the preferred language as language tag or None to use the default language. A language tag might be a [iso639-2 or iso639-1](https://www.loc.gov/standards/iso639-2/php/English_list.php) @@ -2083,7 +2083,7 @@ def textBoxCharacterBounds( CharactersBounds = namedtuple("CharactersBounds", ["bounds", "baselineOffset", "formattedSubString"]) - bounds = list[tuple[BoundingBox | BezierPath, float, FormattedString | str]]() + bounds: list[tuple[BoundingBox | BezierPath, float, FormattedString | str]] = [] path, (x, y) = self._dummyContext._getPathForFrameSetter(box) attrString = self._dummyContext.attributedString(txt) setter = newFramesetterWithAttributedString(attrString) @@ -2373,7 +2373,7 @@ def frameDuration(self, seconds: float) -> None: # pdf links - def linkURL(self, url: str, xywh: BoundingBox): + def linkURL(self, url: str, xywh: BoundingBox) -> None: """ Add a clickable rectangle for an external url link. @@ -2383,7 +2383,7 @@ def linkURL(self, url: str, xywh: BoundingBox): self._requiresNewFirstPage = True self._addInstruction("linkURL", url, (x, y, w, h)) - def linkDestination(self, name: str, xy: Point): + def linkDestination(self, name: str, xy: Point) -> None: """ Add a destination point for a link within a PDF. Setup a clickable retangle with `linkRect(name, (x, y, w, h))` with the same name. @@ -2394,7 +2394,7 @@ def linkDestination(self, name: str, xy: Point): self._requiresNewFirstPage = True self._addInstruction("linkDestination", name, (x, y)) - def linkRect(self, name: str, xywh: BoundingBox): + def linkRect(self, name: str, xywh: BoundingBox) -> None: """ Add a clickable rectangle for a link within a PDF. Use `linkDestination(name, (x, y))` with the same name to set the destination of the clickable rectangle. @@ -2615,7 +2615,7 @@ def fontLineHeight(self) -> float: """ return self._dummyContext._state.text.fontLineHeight() - def Variable(self, variables, workSpace, continuous=True) -> None: + def Variable(self, variables: list[dict[str, Any]], workSpace: dict[str, Any], continuous: bool = True) -> None: """ Build small UI for variables in a script. From 3bcfc782ad83272bb6122f2e73272f48edda6432 Mon Sep 17 00:00:00 2001 From: Frederik Berlaen Date: Fri, 15 May 2026 10:53:12 +0200 Subject: [PATCH 20/29] fix test data a small change in booleanOperation causes this diff --- tests/data/expected_booleanOperations.svg | 10 +++++----- tests/data/expected_booleanOperations2.svg | 10 +++++----- tests/data/expected_removeOverlap.svg | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/data/expected_booleanOperations.svg b/tests/data/expected_booleanOperations.svg index ebc3c6c1..b488b04f 100644 --- a/tests/data/expected_booleanOperations.svg +++ b/tests/data/expected_booleanOperations.svg @@ -2,9 +2,9 @@ - - - - - + + + + + \ No newline at end of file diff --git a/tests/data/expected_booleanOperations2.svg b/tests/data/expected_booleanOperations2.svg index ebc3c6c1..b488b04f 100644 --- a/tests/data/expected_booleanOperations2.svg +++ b/tests/data/expected_booleanOperations2.svg @@ -2,9 +2,9 @@ - - - - - + + + + + \ No newline at end of file diff --git a/tests/data/expected_removeOverlap.svg b/tests/data/expected_removeOverlap.svg index c70777dd..e13f3286 100644 --- a/tests/data/expected_removeOverlap.svg +++ b/tests/data/expected_removeOverlap.svg @@ -1,5 +1,5 @@ - + \ No newline at end of file From 03160e254d04e5c96b01b474401df851e4a1fdf2 Mon Sep 17 00:00:00 2001 From: Roberto Arista Date: Mon, 18 May 2026 19:21:57 +0200 Subject: [PATCH 21/29] promote resetVariations to explicit keyword argument this removes the fontVariations(None) deprecated option after 8 years. --- docs/content/text/textProperties.rst | 2 +- drawBot/context/baseContext.py | 21 ++++++--------------- drawBot/drawBotDrawingTools.py | 17 +++++++++-------- tests/data/expected_fontVariations.txt | 1 - tests/data/expected_fontVariations2.txt | 1 - tests/drawBotScripts/fontVariations.py | 2 +- tests/drawBotScripts/fontVariations2.py | 2 +- 7 files changed, 18 insertions(+), 28 deletions(-) diff --git a/docs/content/text/textProperties.rst b/docs/content/text/textProperties.rst index 58413445..c4928ef0 100644 --- a/docs/content/text/textProperties.rst +++ b/docs/content/text/textProperties.rst @@ -12,7 +12,7 @@ Text Properties .. autofunction:: drawBot.baselineShift .. autofunction:: drawBot.openTypeFeatures(frac=True, case=True, ...) .. autofunction:: drawBot.listOpenTypeFeatures -.. autofunction:: drawBot.fontVariations(wdth=0.6, wght=0.1, ...) +.. autofunction:: drawBot.fontVariations(wdth=0.6, wght=0.1, ..., resetVariations=False) .. autofunction:: drawBot.listFontVariations .. autofunction:: drawBot.fontNamedInstance .. autofunction:: drawBot.listNamedInstances diff --git a/drawBot/context/baseContext.py b/drawBot/context/baseContext.py index d5a377cd..fd092b81 100644 --- a/drawBot/context/baseContext.py +++ b/drawBot/context/baseContext.py @@ -1837,25 +1837,16 @@ def listOpenTypeFeatures(self, fontNameOrPath: SomePath | None = None, fontNumbe font = getNSFontFromNameOrPath(fontNameOrPath, 10, fontNumber) return openType.getFeatureTagsForFont(font) - def fontVariations(self, *args: None, **axes: float | bool) -> dict[str, float]: + def fontVariations(self, *, resetVariations: bool = False, **axes: float) -> dict[str, float]: """ Pick a variation by axes values and return the current font variations settings. + You can reset the default values with `fontVariations(resetVariations=True)` If no arguments are given `fontVariations()` will just return the current font variations settings. """ - if args and axes: - raise DrawBotError("Can't combine positional arguments and keyword arguments") - if args: - if len(args) != 1: - raise DrawBotError("There can only be one positional argument") - if args[0] is not None: - raise DrawBotError("First positional argument can only be None") - warnings.warn("fontVariations(None) is deprecated, use fontVariations(resetVariations=True) instead.") + if resetVariations: self._fontVariations.clear() - else: - if axes.pop("resetVariations", False): - self._fontVariations.clear() - self._fontVariations.update(axes) + self._fontVariations.update(axes) defaultVariations = self.listFontVariations() currentVariation = {axis: data["defaultValue"] for axis, data in defaultVariations.items()} currentVariation.update(self._fontVariations) @@ -2732,8 +2723,8 @@ def writingDirection(self, direction): def openTypeFeatures(self, *args: None, **features: dict[str, bool]) -> dict[str, bool]: return self._state.text.openTypeFeatures(*args, **features) - def fontVariations(self, *args, **axes): - return self._state.text.fontVariations(*args, **axes) + def fontVariations(self, *, resetVariations: bool = False, **axes: float) -> dict[str, float]: + return self._state.text.fontVariations(resetVariations=resetVariations, **axes) def fontNamedInstance(self, name, fontNameOrPath): self._state.text.fontNamedInstance(name, fontNameOrPath) diff --git a/drawBot/drawBotDrawingTools.py b/drawBot/drawBotDrawingTools.py index 7e3fd0b9..9ba73d6c 100644 --- a/drawBot/drawBotDrawingTools.py +++ b/drawBot/drawBotDrawingTools.py @@ -1763,15 +1763,13 @@ def listOpenTypeFeatures(self, fontNameOrPath: SomePath | None = None) -> list[s listOpenTypeFeatures.__doc__ = FormattedString.listOpenTypeFeatures.__doc__ - def fontVariations( - self, *args: None, **axes: float - ) -> dict[str, float]: # FIXME why was bool there? also, why *args? + def fontVariations(self, *, resetVariations: bool = False, **axes: float) -> dict[str, float]: """ Pick a variation by axes values. .. downloadcode:: fontVariations.py - size(1000, 500) + size(1000, 600) # pick a font font("Skia") # pick a font size @@ -1782,14 +1780,17 @@ def fontVariations( # pick a variation from the current font fontVariations(wght=.6) # draw text!! - text("Hello Q", (100, 100)) + text("Hello Q", (100, 40)) # pick a variation from the current font fontVariations(wght=3, wdth=1.2) # draw text!! - text("Hello Q", (100, 300)) + text("Hello Q", (100, 220)) + # reset defaults + fontVariations(resetVariations=True) + text("Hello Q", (100, 420)) """ - result = self._dummyContext.fontVariations(*args, **axes) - self._addInstruction("fontVariations", *args, **axes) + result = self._dummyContext.fontVariations(resetVariations=resetVariations, **axes) + self._addInstruction("fontVariations", resetVariations=resetVariations, **axes) return result def listFontVariations(self, fontNameOrPath: SomePath | None = None) -> dict[str, dict]: diff --git a/tests/data/expected_fontVariations.txt b/tests/data/expected_fontVariations.txt index 25d99ced..5d031d1b 100644 --- a/tests/data/expected_fontVariations.txt +++ b/tests/data/expected_fontVariations.txt @@ -1,3 +1,2 @@ -*** DrawBot warning: fontVariations(None) is deprecated, use fontVariations(resetVariations=True) instead. *** wdth [('defaultValue', 1.0), ('maxValue', 1.3), ('minValue', 0.62), ('name', 'Width')] wght [('defaultValue', 1.0), ('maxValue', 3.2), ('minValue', 0.48), ('name', 'Weight')] diff --git a/tests/data/expected_fontVariations2.txt b/tests/data/expected_fontVariations2.txt index 33186fd0..e69de29b 100644 --- a/tests/data/expected_fontVariations2.txt +++ b/tests/data/expected_fontVariations2.txt @@ -1 +0,0 @@ -*** DrawBot warning: fontVariations(None) is deprecated, use fontVariations(resetVariations=True) instead. *** diff --git a/tests/drawBotScripts/fontVariations.py b/tests/drawBotScripts/fontVariations.py index 64be8ed1..ac49ed86 100644 --- a/tests/drawBotScripts/fontVariations.py +++ b/tests/drawBotScripts/fontVariations.py @@ -5,7 +5,7 @@ drawBot.font("Skia") drawBot.fontSize(30) -drawBot.fontVariations(None) +drawBot.fontVariations(resetVariations=True) variations = drawBot.listFontVariations() for axisTag in sorted(variations): diff --git a/tests/drawBotScripts/fontVariations2.py b/tests/drawBotScripts/fontVariations2.py index fce770f0..3589be72 100644 --- a/tests/drawBotScripts/fontVariations2.py +++ b/tests/drawBotScripts/fontVariations2.py @@ -7,7 +7,7 @@ s.font("Skia") s.fontSize(30) s.lineHeight(30) -s.fontVariations(None) +s.fontVariations(resetVariations=True) s.append("Hello Q\n") s.fontVariations(wght=0.6) From aeee4782e98b8a282bfae58a8fde6bc718d9a243 Mon Sep 17 00:00:00 2001 From: Roberto Arista Date: Mon, 18 May 2026 19:30:55 +0200 Subject: [PATCH 22/29] promote `resetFeatures` to explicit keyword argument openTypeFeatures(None) no longer supported after 8 years of deprecation --- docs/content/text/textProperties.rst | 2 +- drawBot/context/baseContext.py | 21 ++++++--------------- drawBot/drawBotDrawingTools.py | 6 +++--- tests/data/expected_openTypeFeatures.txt | 1 - tests/data/expected_openTypeFeatures2.txt | 1 - tests/drawBotScripts/openTypeFeatures.py | 2 +- tests/drawBotScripts/openTypeFeatures2.py | 2 +- 7 files changed, 12 insertions(+), 23 deletions(-) diff --git a/docs/content/text/textProperties.rst b/docs/content/text/textProperties.rst index c4928ef0..d0e2ca3f 100644 --- a/docs/content/text/textProperties.rst +++ b/docs/content/text/textProperties.rst @@ -10,7 +10,7 @@ Text Properties .. autofunction:: drawBot.lineHeight .. autofunction:: drawBot.tracking .. autofunction:: drawBot.baselineShift -.. autofunction:: drawBot.openTypeFeatures(frac=True, case=True, ...) +.. autofunction:: drawBot.openTypeFeatures(frac=True, case=True, ..., resetFeatures=False) .. autofunction:: drawBot.listOpenTypeFeatures .. autofunction:: drawBot.fontVariations(wdth=0.6, wght=0.1, ..., resetVariations=False) .. autofunction:: drawBot.listFontVariations diff --git a/drawBot/context/baseContext.py b/drawBot/context/baseContext.py index fd092b81..d0c86e43 100644 --- a/drawBot/context/baseContext.py +++ b/drawBot/context/baseContext.py @@ -1787,9 +1787,10 @@ def url(self, url: str | None) -> None: """ self._url = url - def openTypeFeatures(self, *args: None, **features: bool) -> dict[str, bool]: + def openTypeFeatures(self, *, resetFeatures: bool = False, **features: bool) -> dict[str, bool]: """ Enable OpenType features and return the current openType features settings. + You can reset the default values with `openTypeFeatures(resetFeatures=True)` If no arguments are given `openTypeFeatures()` will just return the current openType features settings. @@ -1811,19 +1812,9 @@ def openTypeFeatures(self, *args: None, **features: bool) -> dict[str, bool]: # draw the formatted string text(t, (10, 80)) """ - if args and features: - raise DrawBotError("Can't combine positional arguments and keyword arguments") - if args: - if len(args) != 1: - raise DrawBotError("There can only be one positional argument") - if args[0] is not None: - raise DrawBotError("First positional argument can only be None") - warnings.warn("openTypeFeatures(None) is deprecated, use openTypeFeatures(resetFeatures=True) instead.") + if resetFeatures: self._openTypeFeatures.clear() - else: - if features.pop("resetFeatures", False): - self._openTypeFeatures.clear() - self._openTypeFeatures.update(features) + self._openTypeFeatures.update(features) return dict(self._openTypeFeatures) def listOpenTypeFeatures(self, fontNameOrPath: SomePath | None = None, fontNumber: int = 0) -> list[str]: @@ -2720,8 +2711,8 @@ def language(self, language): def writingDirection(self, direction): self._state.text.writingDirection(direction) - def openTypeFeatures(self, *args: None, **features: dict[str, bool]) -> dict[str, bool]: - return self._state.text.openTypeFeatures(*args, **features) + def openTypeFeatures(self, *, resetFeatures: bool = False, **features: bool) -> dict[str, bool]: + return self._state.text.openTypeFeatures(resetFeatures=resetFeatures, **features) def fontVariations(self, *, resetVariations: bool = False, **axes: float) -> dict[str, float]: return self._state.text.fontVariations(resetVariations=resetVariations, **axes) diff --git a/drawBot/drawBotDrawingTools.py b/drawBot/drawBotDrawingTools.py index 9ba73d6c..a6b289a3 100644 --- a/drawBot/drawBotDrawingTools.py +++ b/drawBot/drawBotDrawingTools.py @@ -1722,7 +1722,7 @@ def writingDirection(self, direction: Literal["LTR", "RTL"] | None) -> None: self._dummyContext.writingDirection(direction) self._addInstruction("writingDirection", direction) - def openTypeFeatures(self, *args: bool | None, **features: bool) -> dict[str, bool]: + def openTypeFeatures(self, *, resetFeatures: bool = False, **features: bool) -> dict[str, bool]: """ Enable OpenType features. @@ -1754,8 +1754,8 @@ def openTypeFeatures(self, *args: bool | None, **features: bool) -> dict[str, bo # the same string again, back to default features text(someTxt, (100, 70)) """ - result = self._dummyContext.openTypeFeatures(*args, **features) - self._addInstruction("openTypeFeatures", *args, **features) + result = self._dummyContext.openTypeFeatures(resetFeatures=resetFeatures, **features) + self._addInstruction("openTypeFeatures", resetFeatures=resetFeatures, **features) return result def listOpenTypeFeatures(self, fontNameOrPath: SomePath | None = None) -> list[str]: diff --git a/tests/data/expected_openTypeFeatures.txt b/tests/data/expected_openTypeFeatures.txt index 7743d242..704e3be9 100644 --- a/tests/data/expected_openTypeFeatures.txt +++ b/tests/data/expected_openTypeFeatures.txt @@ -1,2 +1 @@ ['dlig', 'liga', 'lnum', 'onum', 'pnum', 'titl', 'tnum'] -*** DrawBot warning: openTypeFeatures(None) is deprecated, use openTypeFeatures(resetFeatures=True) instead. *** diff --git a/tests/data/expected_openTypeFeatures2.txt b/tests/data/expected_openTypeFeatures2.txt index e9a529c9..e69de29b 100644 --- a/tests/data/expected_openTypeFeatures2.txt +++ b/tests/data/expected_openTypeFeatures2.txt @@ -1 +0,0 @@ -*** DrawBot warning: openTypeFeatures(None) is deprecated, use openTypeFeatures(resetFeatures=True) instead. *** diff --git a/tests/drawBotScripts/openTypeFeatures.py b/tests/drawBotScripts/openTypeFeatures.py index 8a5a8e77..6ae1c8ec 100644 --- a/tests/drawBotScripts/openTypeFeatures.py +++ b/tests/drawBotScripts/openTypeFeatures.py @@ -10,7 +10,7 @@ drawBot.text("Hoefler Fact #123", (20, 170)) -drawBot.openTypeFeatures(None) +drawBot.openTypeFeatures(resetFeatures=True) drawBot.openTypeFeatures(dlig=True) drawBot.text("Hoefler Fact #123", (20, 140)) diff --git a/tests/drawBotScripts/openTypeFeatures2.py b/tests/drawBotScripts/openTypeFeatures2.py index 2814fd0f..397722e5 100644 --- a/tests/drawBotScripts/openTypeFeatures2.py +++ b/tests/drawBotScripts/openTypeFeatures2.py @@ -8,7 +8,7 @@ s.append("Hoefler Fact #123\n") -s.openTypeFeatures(None) +s.openTypeFeatures(resetFeatures=True) s.openTypeFeatures(dlig=True) s.append("Hoefler Fact #123\n") From 924b6c437eb8f6c9f4a7e0478427fada6c78450d Mon Sep 17 00:00:00 2001 From: Roberto Arista Date: Mon, 18 May 2026 19:50:34 +0200 Subject: [PATCH 23/29] Align all examples to use `newPage` instead of `size` --- drawBot/context/baseContext.py | 6 +++--- drawBot/context/tools/imageObject.py | 2 +- drawBot/drawBotDrawingTools.py | 20 ++++++++++---------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drawBot/context/baseContext.py b/drawBot/context/baseContext.py index d0c86e43..6dca44f1 100644 --- a/drawBot/context/baseContext.py +++ b/drawBot/context/baseContext.py @@ -1157,7 +1157,7 @@ class FormattedString(SVGContextPropertyMixin, ContextPropertyMixin): .. downloadcode:: formattedString.py - size(1000, 200) + newPage(1000, 200) # create a formatted string txt = FormattedString() @@ -1796,7 +1796,7 @@ def openTypeFeatures(self, *, resetFeatures: bool = False, **features: bool) -> .. downloadcode:: openTypeFeaturesFormattedString.py - size(1000, 200) + newPage(1000, 200) # create an empty formatted string object t = FormattedString() # set a font @@ -2183,7 +2183,7 @@ def appendGlyph(self, *glyphNames: str): .. downloadcode:: appendGlyphFormattedString.py - size(1300, 400) + newPage(1300, 400) # create an empty formatted string object t = FormattedString() # set a font diff --git a/drawBot/context/tools/imageObject.py b/drawBot/context/tools/imageObject.py index e71f3caf..0047b2b8 100644 --- a/drawBot/context/tools/imageObject.py +++ b/drawBot/context/tools/imageObject.py @@ -17,7 +17,7 @@ class ImageObject: .. downloadcode:: imageObject.py - size(550, 300) + newPage(550, 300) # initiate a new image object im = ImageObject() diff --git a/drawBot/drawBotDrawingTools.py b/drawBot/drawBotDrawingTools.py index a6b289a3..f546e5c9 100644 --- a/drawBot/drawBotDrawingTools.py +++ b/drawBot/drawBotDrawingTools.py @@ -353,7 +353,7 @@ def pages(self) -> tuple["DrawBotPage", ...]: .. downloadcode:: pages.py # set a size - size(200, 200) + newPage(200, 200) # draw a rectangle rect(10, 10, 100, 100) # create a new page @@ -413,7 +413,7 @@ def saveImage(self, path: SomePath, *args: Any, **options: Any): .. downloadcode:: saveImage.py # set the canvas size - size(150, 100) + newPage(150, 100) # draw a background rect(10, 10, width()-20, height()-20) @@ -434,7 +434,7 @@ def saveImage(self, path: SomePath, *args: Any, **options: Any): .. downloadcode:: saveImageResolutionExample.py # same example but we just change the image resolution - size(150, 100) + newPage(150, 100) rect(10, 10, width()-20, height()-20) fill(1) text("Hello World!", (20, 40)) @@ -493,7 +493,7 @@ def printImage(self, pdf=None) -> None: .. downloadcode:: printImage.py # set A4 page size - size(595, 842) + newPage(595, 842) # draw something oval(0, 0, width(), height()) # send it to the printer @@ -671,7 +671,7 @@ def drawPt(pos, r=5): x, y = pos oval(x-r, y-r, r*2, r*2) - size(300, 300) + newPage(300, 300) fill(None) path = BezierPath() @@ -1544,7 +1544,7 @@ def tracking(self, value: float) -> None: .. downloadcode:: tracking.py - size(1000, 350) + newPage(1000, 350) # set tracking tracking(100) # set font size @@ -1587,7 +1587,7 @@ def strikethrough(self, value: Literal["single", "thick", "double"] | None) -> N .. downloadcode:: strikethrough.py - size(1000, 200) + newPage(1000, 200) strikethrough("single") fontSize(100) text("hello strikethrough", (40, 60)) @@ -1664,7 +1664,7 @@ def language(self, language: str | None) -> None: .. downloadcode:: language.py - size(1000, 600) + newPage(1000, 600) # a long dutch word word = "paardenkop" # a box where we draw in @@ -1711,7 +1711,7 @@ def writingDirection(self, direction: Literal["LTR", "RTL"] | None) -> None: .. downloadcode:: textRTL.py - size(400, 100) + newPage(400, 100) # A bi-directional string s = "Latin میتوان در بسیاری" # Set the writing direction to Right-To-Left @@ -1769,7 +1769,7 @@ def fontVariations(self, *, resetVariations: bool = False, **axes: float) -> dic .. downloadcode:: fontVariations.py - size(1000, 600) + newPage(1000, 600) # pick a font font("Skia") # pick a font size From 839f6ad6bf83be582979ec0f50cb0d43471632c2 Mon Sep 17 00:00:00 2001 From: Roberto Arista Date: Tue, 19 May 2026 08:44:51 +0200 Subject: [PATCH 24/29] Revert "Align all examples to use `newPage` instead of `size`" This reverts commit 924b6c437eb8f6c9f4a7e0478427fada6c78450d. --- drawBot/context/baseContext.py | 6 +++--- drawBot/context/tools/imageObject.py | 2 +- drawBot/drawBotDrawingTools.py | 20 ++++++++++---------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drawBot/context/baseContext.py b/drawBot/context/baseContext.py index 6dca44f1..d0c86e43 100644 --- a/drawBot/context/baseContext.py +++ b/drawBot/context/baseContext.py @@ -1157,7 +1157,7 @@ class FormattedString(SVGContextPropertyMixin, ContextPropertyMixin): .. downloadcode:: formattedString.py - newPage(1000, 200) + size(1000, 200) # create a formatted string txt = FormattedString() @@ -1796,7 +1796,7 @@ def openTypeFeatures(self, *, resetFeatures: bool = False, **features: bool) -> .. downloadcode:: openTypeFeaturesFormattedString.py - newPage(1000, 200) + size(1000, 200) # create an empty formatted string object t = FormattedString() # set a font @@ -2183,7 +2183,7 @@ def appendGlyph(self, *glyphNames: str): .. downloadcode:: appendGlyphFormattedString.py - newPage(1300, 400) + size(1300, 400) # create an empty formatted string object t = FormattedString() # set a font diff --git a/drawBot/context/tools/imageObject.py b/drawBot/context/tools/imageObject.py index 0047b2b8..e71f3caf 100644 --- a/drawBot/context/tools/imageObject.py +++ b/drawBot/context/tools/imageObject.py @@ -17,7 +17,7 @@ class ImageObject: .. downloadcode:: imageObject.py - newPage(550, 300) + size(550, 300) # initiate a new image object im = ImageObject() diff --git a/drawBot/drawBotDrawingTools.py b/drawBot/drawBotDrawingTools.py index f546e5c9..a6b289a3 100644 --- a/drawBot/drawBotDrawingTools.py +++ b/drawBot/drawBotDrawingTools.py @@ -353,7 +353,7 @@ def pages(self) -> tuple["DrawBotPage", ...]: .. downloadcode:: pages.py # set a size - newPage(200, 200) + size(200, 200) # draw a rectangle rect(10, 10, 100, 100) # create a new page @@ -413,7 +413,7 @@ def saveImage(self, path: SomePath, *args: Any, **options: Any): .. downloadcode:: saveImage.py # set the canvas size - newPage(150, 100) + size(150, 100) # draw a background rect(10, 10, width()-20, height()-20) @@ -434,7 +434,7 @@ def saveImage(self, path: SomePath, *args: Any, **options: Any): .. downloadcode:: saveImageResolutionExample.py # same example but we just change the image resolution - newPage(150, 100) + size(150, 100) rect(10, 10, width()-20, height()-20) fill(1) text("Hello World!", (20, 40)) @@ -493,7 +493,7 @@ def printImage(self, pdf=None) -> None: .. downloadcode:: printImage.py # set A4 page size - newPage(595, 842) + size(595, 842) # draw something oval(0, 0, width(), height()) # send it to the printer @@ -671,7 +671,7 @@ def drawPt(pos, r=5): x, y = pos oval(x-r, y-r, r*2, r*2) - newPage(300, 300) + size(300, 300) fill(None) path = BezierPath() @@ -1544,7 +1544,7 @@ def tracking(self, value: float) -> None: .. downloadcode:: tracking.py - newPage(1000, 350) + size(1000, 350) # set tracking tracking(100) # set font size @@ -1587,7 +1587,7 @@ def strikethrough(self, value: Literal["single", "thick", "double"] | None) -> N .. downloadcode:: strikethrough.py - newPage(1000, 200) + size(1000, 200) strikethrough("single") fontSize(100) text("hello strikethrough", (40, 60)) @@ -1664,7 +1664,7 @@ def language(self, language: str | None) -> None: .. downloadcode:: language.py - newPage(1000, 600) + size(1000, 600) # a long dutch word word = "paardenkop" # a box where we draw in @@ -1711,7 +1711,7 @@ def writingDirection(self, direction: Literal["LTR", "RTL"] | None) -> None: .. downloadcode:: textRTL.py - newPage(400, 100) + size(400, 100) # A bi-directional string s = "Latin میتوان در بسیاری" # Set the writing direction to Right-To-Left @@ -1769,7 +1769,7 @@ def fontVariations(self, *, resetVariations: bool = False, **axes: float) -> dic .. downloadcode:: fontVariations.py - newPage(1000, 600) + size(1000, 600) # pick a font font("Skia") # pick a font size From b2fe5a082987af2576f277c1efa2979285561953 Mon Sep 17 00:00:00 2001 From: Roberto Arista Date: Tue, 19 May 2026 08:53:42 +0200 Subject: [PATCH 25/29] align to the other scripts in the folder --- tests/drawBotScripts/fontVariations.py | 46 ++++++++++---------------- 1 file changed, 18 insertions(+), 28 deletions(-) diff --git a/tests/drawBotScripts/fontVariations.py b/tests/drawBotScripts/fontVariations.py index ac49ed86..a95e0841 100644 --- a/tests/drawBotScripts/fontVariations.py +++ b/tests/drawBotScripts/fontVariations.py @@ -1,33 +1,23 @@ import drawBot -drawBot.size(200, 200) - +drawBot.newPage(1000, 600) +# pick a font drawBot.font("Skia") -drawBot.fontSize(30) - -drawBot.fontVariations(resetVariations=True) - -variations = drawBot.listFontVariations() -for axisTag in sorted(variations): - data = variations[axisTag] - # we're rounding the values so we don't trip over small differences between OSes - data["defaultValue"] = round(float(data["defaultValue"]), 3) # we need floats to make sure that 1 becomes 1.0 - data["minValue"] = round(float(data["minValue"]), 3) - data["maxValue"] = round(float(data["maxValue"]), 3) - data["name"] = str(data["name"]) - print(axisTag, [(k, data[k]) for k in sorted(data)]) - -drawBot.text("Hello Q", (20, 170)) +# pick a font size +drawBot.fontSize(200) +# list all axis from the current font +for axis, data in drawBot.listFontVariations().items(): + print((axis, data)) +# pick a variation from the current font drawBot.fontVariations(wght=0.6) -drawBot.text("Hello Q", (20, 140)) -drawBot.fontVariations(wght=2.4) -drawBot.text("Hello Q", (20, 110)) - -drawBot.fontVariations(wdth=1.29) -drawBot.text("Hello Q", (20, 80)) - -drawBot.fontVariations(wdth=0.6, resetVariations=True) -drawBot.text("Hello Q", (20, 50)) +# draw text!! +drawBot.text("Hello Q", (100, 40)) +# pick a variation from the current font +drawBot.fontVariations(wght=3, wdth=1.2) +# draw text!! +drawBot.text("Hello Q", (100, 220)) +# reset defaults +drawBot.fontVariations(resetVariations=True) +drawBot.text("Hello Q", (100, 420)) -drawBot.fontVariations(wght=2.8, resetVariations=False) -drawBot.text("Hello Q", (20, 20)) +drawBot.save() From d67d2ad7041d98c07f56276cca950cdf215794e3 Mon Sep 17 00:00:00 2001 From: Roberto Arista Date: Tue, 19 May 2026 08:53:51 +0200 Subject: [PATCH 26/29] update image --- tests/data/example_fontVariations.png | Bin 28249 -> 50221 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/data/example_fontVariations.png b/tests/data/example_fontVariations.png index 9151b02bee36e22e3190755f00be05d996521463..a0899751e5ce9a3d943cfedfc1a8c38b3346eb39 100644 GIT binary patch literal 50221 zcmeEu^;?u(*ETUyQUZdMAdLtJ2uOE#3kaxmOXmP1DoQufNJ=Z+p>#8J4$?hz3=H#K zct7|3KJW9r|G;;A?++Zu#c;9L-fORQ?iJ^r&zkBA1b9?6-?+M{P%zuY2twg2lmd6Bp0BbouFk%>fBtek4IZ$u=(fLjH@fbL zapEE~#uKVC&b6`S%I@`!4q^9p@CX5Tgp(sO;c)^BI`zuW*4aHceb?gDS?xK>dZ$cN z0sYg$hv|~%eGJQ%XgBveD@=kwQdd2=Q*SPCJ477P=$A=;Riha^$RIkX7*3Ai{bVNh zgsmw2rep3C_6Fmb5eVDuU@lUW|63_LL%&?FKyivX<5+X>RbY+Wf_=wautrqnQ!p6} zv+gYEv1{V*5aLX|)p_?%Ml_SgrVp-ohvFUPdVWnbo9=~0f}?F5 z1>?!q#IRs*k9N_%u6^0-Y96yRJdXhFH2igi#Sll`!jqkH-V;vEKs8A;MeGtOGFE@rWhrfK-@Jx@KZ zPZ6F5>B%_Du|gDgslu7L^{Wr1djburS#ycaYTN^(mgjra=HmL$Gg~vM)->bj;`UyO zcijIH(JR^h-e>pz(^sUj(ey;N{>HCz3h<~lZN6^i*?hg2SlWgCWWT&YtJSr;>Dk#F zeJY)gVmufr`U$tuV{F0?@UbcO7{RrA%Q()X#H|z?d_ltyxB8UwQ4W19Yp;$)xW%Zj zG9iC=B7>X7asBAH4?3fEreIi8*ru0M*NwHsm!+!VPUTEN;_2b(Vf(&>DJN55u#-Vp zqr84*|8!QmK~l{5wFClFTK<9jE!c#u`!SBG&8;7y)l!8=Dx>dIFe`>#6f5vdNlO^ef(cN{QqSHl2jN| zD&|-me;gqC5oE5v!0XO6qH6mg)i;>@1eLj6FsZ9C5jw+I#;tu{M5?;s_Z$TQ+A`)h%eu9|Jl*9N0RS`ByUYzlN(~gOH~TPn)#+Nig4_BulA4Y zza>B?amT^{RVm+eG5`Gvf?o37BDTludtjgu0$?EOQkZcA~wC9O>xJM&#opH(z6JMvm7FWxz}gu>R{ zd#A5pTS)G8_k2^%as|k(99(pg6ZNNKIJfgM#d%5Tz~60A)Ai-uf~*G)eq>up=*2#C zAKIKto13awNj5kAwhxcOt~pbQbzsZSxA|rEt(Fzl0gVf3<4fOa{G;Tv_I0WghXxV_ z`lmJ+Q#vPJ31`u1@h}}DIeBo!KQO6;6P?A{{^EU1>DpQ| zW(J~Uf)(>Lwr;fV86VTsF^ zg3`~qZb)0)*)E)&uE84va)awYPm%E`olP#F6;ZUqw=<@>$B2sYrHb+mVaYdORzD*9dReVIB>I)1A4bBDCQLS=oB4LtfL~}<)T$;EpBJae= zmh>|QU@x!iFqjB+avleCZbmkse>WGodiwU=Lr!)C*EZ&9KNInSl^cy8f0yq1=1+T^ z+(+N@2AXt)jc3h_6pFsiOG?qOrL#7hG!)9-Zr%4Mz}8vb)2oyYrQO?%bm4z$jn9;l zTd>(kX<~J%j3e8v9y#Y9!K24JkAsQ9cW>IrzSTfj$2ViOv1sarKVKs zO&D0=w{$dI-#sx=Ix}E6n`|NY;P*wj83oeV*P|@6E*PUfC`u*vRf^7U?NO%_LW_f+ z5ag`sALL$iqH0TEi__^Mt{^Pq+YrADl}Y{zm__wHda3eK1&SzEx!CT=y=DI-1WO;M z9E@{~4mP1eFYK9ZUQ1BH-!+cK>L5+8fDzz%Nt8FGQmty4nQ%;?_ZtkY%@Y|iNjG=q> zM4o*Y{@<6cpn=LV$#PGbsq}-}z60YC6`*u><9R!qXS_eVGD8__tAA5oRuqMLeA(7HsDB-*0T_lR?tzR@T1M3V zcnXG{9M9dN*+1r=bVH4Zq4YO|C&`oTjl*}ToSLRW(^_m?D9Y+G1sk$3vvwN z2N=L!J~}z7=84TZpPCwdPjA%P+GAVq46KY4K!NN38Y8032yZhO>X)0A@9cMlN_Q`F z{}HbJTa4H8wz9G%pQjI1=$8lJ1RB z04Tcr1B!MG-y_~#mbe!@e0PL0Hk(44Yzaa?K%F;Ck&C^T7bsl`3`ZT?%KE9%E6&r) z7U-n*)Y=ET1AS;tu1bSb+8F>IH-JjdVb~@M;2L0;svQoY)a%$s6O3(#nxs zX*Z&@79nDDF=h9ww=T|=j`(f%g8b#@aH9}K@y!FxUfin;Xo_}fr{L7p$5o4kLv3Ig z5aK1O6Nr1&&v0Nrbt6S~m``5C8;7=VKuE>&S&3;yMiE<#p{T^Q2RhVg-*F*axEDT) z-AazE8x-FnzT6UA9*9`OSfbk=WXasJpx0)1<|2>q>fD0ObxP-1amVPBz9zs{mp zjK6t9P2VK%wWV!y4OJT#h(4MKkl~NWcGS>j@)?z_+n-R>9d>{at@L;1;2;_SSE zr`b%b;{b5vQ4-Tj4QG)GyFx(Cj3alSk&4|-&W4k}4U@y9C#LlS!T|b61R3DOs?+Z! zl|Y1vl~MNXzv2D)aW`}|uNv*+42s$*6gA??Y`z`_TZ|1W769ORp9BEU?>ZE??45>; zo(>d{#(`zFD;uQc{K`%!u59fL5Y3FpgF`2s8Ce{pv&b-7x)7F}&##nbnxb^)j$0(2 zQY6uhCN@l;Md(m>J_Ha!0@$>ht1J#8?X(ZfS`L$dU5p|IoAUJuZlj+_bHH)z9@uwi zN*{U4SQ@^|e=E(%ilkqw-bsgWgyRADVjAfb~;WR+INcicms1wuUAAogb zUP5*dsqC=0k3?x+)xJMd=JQCTX=y##cpnKr(i7Qu?m)Kn$Hr@|iezdI-I@vp5eRFWpK|`3>e9D9eM551u z{r)NP7VA96`n3{?b&%K(yLgkToA)CAG{lfi^|!#1zx|gQ8PPS;#hJdEQ}j>9<@S@# zKA9OGb-gLY#hg~HAyoWpavHaj!+^q`&i3EoC1$>Hst ztuwl2J|YbtR`+^lWshoB_iUKxM(Si6-1jHoDEf59OQYG!4fhmN)FZ8J`Xy_J0#Rze z_q*V4gwK?64p2p`iW2dYO0Q-rADS}m#kG;M{K?s~EHTbw!EhV?1g}1}L7Z#Fi4<3_ z<^q2EnouKk@`q2F<%E@7UGKjZGM&OMZDIAn+u(w3Ydfy_;@OC<8^W%rdgqlRcs$y@ zRrrs{wlJYW&=T|4^{44=blg6EzCo*wN!nZxum00Dg#RpjIH@$EPj2+{#;|J79E#N$ z_Ic{rZN!L%@d!ht_^b-0N?|lS6{(eS?*dZ9+2KBGiGr5Qys^K;4;p6kmph`Yw-u6` zI({IbJ*!b<8~W;fzv-J8^Fp3{f#=T5IjBeJkLAAb7y8xDUcX!AiC-Sb8qgGG_+C1z zbUAm`6M47=OKUY; zqmG_!c6T(HA&RSrL%5QVCgM$MN6&_#D(~l3cnMm%zG#0vQzfPw7co6buEHtS^+2&m zh%+o`Wv^_h8kUOOnZ>ca~ zgcUHq6nQ+;ZtKgY;|vvEo|g2B5=1ex*_EjsWt8>gdDP&uO~aK3W)f3hw6o686ZrBD zz1{p!tw(Ti_II7~93X!!T`Vxy(Tt#W_tMb z=9QIkycI}Yw;Jb)Rlr{0%1AIeq&&etSK?`b5NmPxzamAL9>n-XC)n z(WDoWzMjo33#32>evYMpZ1kqHAnP^Lqt@;l-CK0v;0CYMeefP?*u|JJEdBJ&h2%Dq zki^~nR%eZLp)*7Mgt)5QJHwSaYkAn1zfAjaL$NiktNR5mJdimPT(79a%**$CG#Sgt zTvbgIW|YvvmhgS=$!d=Cxc4{RBmDdIW@?874+6P3#|76ykvG*&R z8$8k{|Jd;>a*W!szRH_mS~J*Z+&oH%xt?R%S_#}9fqg~%V{_%BUL~)Y9a81KOxfoh zX~uD-5$(e#rzT}ClMlwE!L`#BgQuOpp$SlJq(Pros}@atB!9iY7uP_!6uW^Yx2NM! z>}~sQWFU*2nLkIf-;3My6%C>ba$=N;p}RWP5#p5;F(axd|D7_k6V~1sOvA7u=wXuC z4*sDl{h6sUs_$7Fm3azzHR(*NQen3{;o0KXy2&r(pdDt`1Br?+Z)h&gU9MIa3Hq0? zNl!mqjg76d14t!jTKR1tP&!dE^vaYT5|%B*2up6C5|Gd1^I zvDoTiyw^xdqT)inqq+|FvO(_tvzF@mA#~n=_f<}*5hpfRckJf8kc$-xbRTD{GL7MU zo9um~yso}@GMF_kFMdwDiH)Q@l~t9>;sP>IkJAn9QQ5dAo7nnz=juQTO9NNw-{~#o ziu?l@FKp7pjqgUq(pX32t^TNe5g7kqY#VRAHFruy{JE~%j8Z#NakhS)o-ce4a%4Lw z8*oWwryL&SjPTYT=^LG2`wH_{xFqfWp?F35b>p0u;Aq=@@aYI(bCj6`}SI23uw$6w|=SI=|Fk+ z3ihSsd4~iV^iCQ2TDu#wTl!Ro({h6a^F~26*>eFH6tSt_c=DAL&qpv|RsGnhvrm$G zFLN2>%@+$DAH$n&AvwH=e{J8F$Z67nySnMu zjXgUF++u;QZ&8L+VTBKGaZAD^#ew_i(qX25FL}rS^hR~iq>PE3zv~&Hl_2<{k&H4- zWkSrXhA8fO`d4)xOXu83BorO$qMfUecr*b^?rdgK76B0^&8#6_rNE<{yPKtqPn{2* z?Isy_M_J6Uq4TKVvaz-r92V z*%e*yl<#~w57nWq!opCQd9Y z9+?g2PHe`^tIjP8BW?9k9DTsD6R02{W*idxF^C9FgV*Wk(%5#sy$=JFk^C*nzZ@5c z#DGK1LiQEkC3H1&|63$HQO#C82e;5wGsR9tz)VuD|0d@$odMe9ek`M)1!95#?UT4Q`9MChhErSaWNULJH$SLg#UqE)^e zIGxK-s)RkUk%7RZJ>~rS)0IDirq)EZ=1$3)jW!mP-?kLQ1H9N(p7btJM z@Tc9xLhrtw&c#-wz;dWEIW4qXvWCcCe@e5yv#nF@gu$)n?WIh%jOvLj=)3ait|uRk z^@%@OkR{w_7O6MGh-VwuAD9=7(Q_hB!dWG;YN_q;s`U2=Gt{>-`BO)>NeUWX7SeJk zLfKC>7nS-ww$j-z+t@0qPnhffy2(GAF=;A2qo*#9fEyIG`bI$}U2A-3UK8+Kc4-tk zWq9U0$Pp$+RPHS|7v!UKLmdoq8d{FUSgBJ^XInlamR=906iniS{CjoXyHaYC?^@Z! z=>fTQ2F`&-DeHmQvmLs1#m|#bRVKa*Y>hyQdU3hyvwFUAw+J;OKx5y&epo?S?>YH- zdd2AAZk#2lcf`DzpcGEa%{dR$jAVMduOoAOgprvp>k~QM6ZdSTk*_5f zzYB`HJ2Tdz@>n9KlJ4$vf9r__cFoKpk9*#6Ka~zq=a?1d2}a^f-4e-dmui+P zcW`&{2W3NL_jbQZ?eHw}kyL{#Wj&u_qT^J_(r+|2*O2jAQIouN{V_5ak|wIoAt=_e z|0c89U$^PTBKf5NqDhlMv}FLUkV)a2ejRY)#ygmqdZIRe$VA;E4uFE`VH> zYy`>HS+O-U%NrCx+Z&qvytL&kdLi;?bm2Mjfo$x+BVE?#vz4PuJVeJl{CO22d;LH(<=^=o+FQ? z9hffbl9Ad&XqCviwAX>%ki&cwC^{=}TgPSxN+ufUpY`ZR_#pYXukC6XqwpGE3^j3A z%ZN>jXgCJ2j_j8~8gw}`+r~)VFKvVbvP076RsFRHkxwByF^1x}DcoJMMIdB(r|ip+ zoDCKnMm-qo+dHH{S|JUj=M>pLd4c+3Y!Ez_Mu_k9-bA^j!q8{gv1RJ_9wz>!wqqoP zb5(=3+j7^T7MIFOlhQ!DM@noH2Nda2-G2~3d~rlozsd%1w`dZDju^Jg-4W7%@ACGm zD1%hTMo(7($#m~T2kYvK6UoK(3YYVjm;*iBBq!m*=2!;WG{ldjGSQzGOJ@;b#L(`G zU+1ae;KxW3TK6;bekiET)YR&})N)Y^^9rwVG)nfBBRxo7u<^;kzYrcb3X3BeuKAp( zpg@41C64QxoSw!Yr7>}CNz!4DLna9X&_U`y<#0|^UlCNd`n84R=$(g3BIk>4qzI9` zOXHEZI*w}-a24_O2_Ales@3(oeDw}ZhX!A1Nq&;WpW>X1S?=eTpHW|@>z@4&ix$SY zn4RfKFNi9^{Dr3_JCyC0B4YUh#DHBVpBp)r+8QOUd%f+r6V-m(ZMa)cM&Y)>hI3q7PkorXbh zAatC7-l)c|qg-*plGfPb!=`{mrI}fWr(;;Tz9g&SXysB1A@X{5i7A}5Gx&EXNV+`9l-d7icPJ{XD6>K4#FvAE0EPpZfh#^TG^wbpDwfFnsS z8^pf<$X`y6%Q2*etu8@?T5W`*o6pT#Fu5M1Fa}_srq+{sTR-n=z*=+}*3iLcUBawB|igBqi&X_9>uF&6Q#tOSSmbScp z)v?)Z)(vZ1yx17M`mjsjlk7}fi;PCEA{Mb8SI=w^@2Joje| zw0Yrg7!j8o_^iatkDug(*U!5d4-MIvB8NC z8VF=xKcg=07tS%|Z_c>Y3dQdXEBGT@SG>1)a_$hAf*q@z$pv$hu`6FGCuF%P92kD< zo>Gg+0_L(v^dd;I7;s(VPU8d@2|q73iR~QByM@BvR~5pAqzZCb-*(7sRZ@YFx_?$88@?@O>)ysK@C2(iZ{1m+7vp&6PKdr0ZNP=l04WDa-5Uo z@aU}Ck*~ZnYla0q7oW!+L*}dX83W|D1wOMk5TwuKj^b^n6@-Zyk~9Cszac~xes?m&)k-gX~)B1-x}VkA;iy$&5ywmY7* zV*+EsH9fwq#uk^vo**O9qGv zXbWq=bx$YG%{5eJNakJVa^UF{ldq3=>_eFgMto?%!}WCw5_B~6Am-N@7^<70S6sW7 z%gw6D)47l|s0o;6I8Z>go)`LT!eJRA;4-cEWv3FZI5I~mo%eRnZMRycWv+mvE;9#T zX(TlYwEwi_Sz~45jc<{&v%rK=N&LGuPu%cpWr2^bzhI!cr|6IXoVOI`0d?o2cJ8b{ zh%#*}12INrD^^9OYn4#f0ufO&kxu8M2=g)~zuU%sV4`I9T+|$cROW|^(4E+<@*eXe zolw5bjJzdqF9&PHv5*jiY-~=*FQdu$DGuZWFs3oS(up@oBGuKrPk73Dba&&(4$_tJ z8yGTk<{W{-FWYV5cbJ3}7xAP@-&D|-z!&d^!%uHGmdtv@;C`ed^F!;Yn>yfx&*b5h zq`!-y>N1>7E$ourpAJ>WpweUnpP5)-d;LN`)hhdXCgeH$Mq67oX3x3CY_X zTsx+dCRH2a*HlL5I`;8m(1(a7FydEO^#h`e;}Z z+lly_%EU8JwmGYjgc=!#(PyA*(wZ%(5~v)Lr4TosCpK_3XS2(Gv7yGczHp}~z-OR? zzZxFXCLhT%8LvYZzsT7vHLI{)?4AEpjPzN6G6wY*fFoga+fCqI3Lo&Q*GbWut|MV0 z_EG1;^(79#ny|lK*yPP8b3`%*yNo2=9bG*n0t=ZcHX8H~n=u_!cYzj$sZk$K#(Biy z6Ibb7;$D}N*27ao0^UEiQEWEB+W>%L1KJh|dZ|Rp?)i*EipTANmggvfPefF|9W|0l zPIn0VW^1|4{AgrjT8X3$LtZ&_3wq}|(_@stx>R!%p-#`Zh85F?S$I_na#=JIuoI^D zWOv@Rvs($HtwP^>g7;iRue{^l#%vmj-}~8UU_^w?khOVm!J z?tCYa)OiyBYJ{);>9~B}iZ#?XwOF9$tnkMPnKZOz>Fw(>cQyqFqv09uQ0(0#!X)~ijz zeMgS{BogVc$aET%LOhv{`_}vx(N2o?m3R77PYd$%Zo3 zi>%EGMqtXjUZdx9FRaqz&8`IDi@5l)S*$^yaBM<`|VeDC?$ z96YSG%H?hqjm$?MyX^rN{vKeVH>^JW{EegsxcjCuSl}A~4eqi4&@hhNe>S$J?s%t8 zALkL!%?P|>ZFT*2F?>g(O#Pj>QtsUFUk&)Ge`%Dr)c^F!eexGcATTe{*zNM|Hue z~m7l`>VWhA21qCd*)*nC<$iIwT8 z_j`xjIy!j_gQvj3p(+yu0#hk_l#nj4M@*Inzo}%)-pxKu^$|1MIk~KjSQN|E;(VM( zPmGL!`|WaeWL161#%=Jr33)MTFaqT3WgB98B62gVA7T<6Uou~{^v=OZYgUrqh%;tZ zT-S>IiLPrC*bO1hB6xpZ9}JlDf4QsQj=P5h2@|6jeOA z+Z2zd%UN)|#b&(KF+@zhT)d<5F%Hc<(VsXrjyX#L6A^0PWw8v$m*c=pW%QZVS zn!el~WJ*5*B-${}C8%mxRW=_&ikOs$KUC$%JuBd1*1W*Sv4!6HW|bdEN2u$!!S zxEn+yhp%}X8;3~3L~f9>Vgvd)B6*{TU%3H}y}sVjZ6&c*mo-C8xf?FG-s)HYbGD zeXB*aE56Q|WA0)k4CJ5n7-*Z5LN+7SHJrvAFfm2}UKA3G%RqdK?T#kDGNuY z(i__ZJ<}&5#Vi#QACfnU?$Ko_>eVEE&G+(bt=!(vXuFqR`v(+HZaV=)+sG=)y&Z8+ zyQ@bDEfcpa0J3{vE=Y`DZ`T6pbbH4MD0|M4(A=4Kmc$$}X+caN4qwbtFVxE(n?n`0 z0U^oh&0MOUapB~d(QIJNCb^?t2uJ1Yx=yQW+>dl-k~|`u`E;bX)b&bL)^OwL8H-49#}~yBRzH`m z;Zb&ELGLwPlG8h9ibn_LoEiz!v`>sj71lVHtvJGv)72r$1x!`@g*TN<^FWQJo5=>Y zn{(cxxP*0E%V7bz&R^P*V0$F867TJ7svjOboNSZ_TGj!ND?*r`x*N<)3qojBRTbzP z78G_gHr5>MYb5QvzSrJ7?WnCL|v7NOz?2*KeU-A}Omp`YA*Zqv=3> z94@=a-wi3{V9esTUdVP`(Uk zSA9b!Bs1H61Lfl*$UNQ3r`M^cTDA(dh0EPza_}3ctMXV;%S@ofN~Ro?TRakJzvNj} zo+Hvp@Ukpl`S#3v9Bt5}8Jarez#yUyW#1$HfO-ulTPklFKpYY!} zQ@~CaQ#fstqdJn zC4^M&Onv~4A;##HA%lSU?E^NzqY)mO4&-vT%H}JlC_5G4RR8ho$YJKN+9%!_nsTx~C zddZO=$LdZ|iaqV3{@;f>TX6$pde%ij_OSufn&PQTD!v96Ox zU;EfT%|HBc;W#r(|LcMMTU+WoJVU;d=iI%-(px;Vl)I$oU(2^j3+Hv)Uvdo!i?dDz z+No*seztVGjCl-k4+P5`E%d282~gc!{bG-p!QMVgR9Chb!`23fbhmBq2av`-SUyVe zC4Bzp@?h_R`I_o`WSkqG)libhiEkO%XZxmoBFlck-mkgLZ~2m`H$-=?Frf``9Y$L` zd*p!h-+HmuaueE%Ws+93sc}0fBZ0|pcNDE$F4o`2H8Ezwk_`RF8dk0t{U7s$;dE;) z++7)g`3l107)|Nmcv8FgS5tAJdcf_v3@>4l2TA}6>f1NxKA?k z+#&I!p%)8A#*g1jBi0T&2^75}{W_F8BauWHV%o|+Z4Apdth$%S_b|r+rvny#gEMce z7L_l^K?)ef_kayK3q1HA2#)B)d8O$45&ot$9Z#R|3E6e_qt;cD9 zeS6E{nOj~}s_vUZ_Y=5s7?NDeV#RO#<4G!Jmo3mPCZ;UyteqoaN z^=ttFRS9eaUS6(k!4b~VH=YMIrx0|U&hY-xqWjZbVyzF^>r5L}D(#_VzYJ6xRQCu;opi@kL8~KY6SZ=%-P7X=%GqXz$*dJuL8$xilfmmh}^NbQ+pg z1M|Us{_|P#6nEGC8G0h;cF$CnR+g13MU(JOy2A8s74h$XsQze>pSYr`HwuxfH>C#` zSMI28sWa}au}jLiMXepb8aay+PJ=0I%(QU_4y{C%w<6$Xn&G^bz+cdHzss7MF9PJ9 z$HB;Fiy^S+QZ?VLBT5Oy!?5E^RDaYsE6p zNSs0yrUxcDacSwZEMc;YRlKxm7A$qBIA`YXTD^L5(FQP6Ml5E^E$nL-{kDy;MeiUJ zV&lqKemv3b#(t#y#gIv`m@A|7kkj_7xblx(i#Sd|dWhY*$%A^5tQi4BOCSBn zm7P{*nP~nlivez;vkC9k%jSZ%hfhwEdln`40<}|4IFDuo**Ff%PF)-ODj?ZM&d#|S zNyUCmyD*c!=8L0ZXXXA*zMXS%?~R>#fX#A?#+2x0mCtr0J{+DRiQYlO+lK!l=@8jX zI>4*ba{a7*C%tt_0`q5)O{=!wA6{jU?`?1qm0o;&c`w6xkoZLe59RS`o_U^PAgAsW zZg8@Pp?}0>Sl;+t>+nyBx_(I;`^Ol9P@_@I(Yp}~y_T6eBDE=fIZg&g)yH&+O_|TO z+(L&7yr>CFrO+_Iq%TUHv29v`UU4PcC?fq%%4?b1U>p4CGN0RvWe;k{-+iEJTZddG0J!9beVZ6)G z$yvuNmd)qh0pyDqGiv?HtG4t=k@5`bF3xnx;$f`>PD~%a2+LJaal9#;*FI}D0Zab5 zo)RP}2RhSwGRj!*c!ODlbE^C`jn)EA8xtEAH)Wo;dBIV78=F!H4KSDpA;l+wykJ*|%rrD#8Hg6uDM^OBm~) z2u_5ZdsN-XFhxaiktF<@Ak4$Z$WS`*u&qB#I=WJsSk!{HDzzxc6~*BS#*~JrgeWSg z1V(Ek#ELmlEb~UUN=X2A_~-)1IYTnE#Z+(ohQ~S9ONZoX?Vs*#dQn;T;Bnrt3OuPM z(T*Fe(fSOw8EFRufnb`y2+}N$H?nur&;s>bdFSO_r1v}Kee+hCHZZobg^=py>WY)` z0_h_WC-oeW3g1etRpNPZt___KLp$)8jLDdO`(j#HYMZMI!xiQh{uYH>dF%Mjg{7*& z<}np?9ZF8x@If4==lU)~=dhi~Z25QL>7w|*oa8xVqX%UeHK|_K>hv2Q;fk7)I&+5i zA12P4Xm~as>mSdYaNLJIv1T%s2CE(M*V7IkT^`iX+@1E27E-~F+gX1w_U3sLV?e;u z#oh}Q#5H-R=`ZxYPDJh58n<3h{mszE_SCbv0&bl{saxuXCOf1oGRPpb{M&c!bSdt~ zo2qFM`>*78tl#|>7QD`R@y;NItnmHJly-NMoM9(%{2B%+;**|F2@A0aBSyHMD-^B{17hQrff;07zs6K#7({&+y zSc)T8J3BV-(zD@+uztXJ>!;NYiI<|9X!}f*~R{vMtA=k53f{{UkqtvPFdNGZYHsl8MY# zvxGW&`No3>=fwsOR-mQ1)`}Y{{PC51xD3K)uGe&0=BoV!6q#}XpHH6m@@d*}n(4gq ziV1jWAA}jvf6jZ5({q;KPy3vi0D`n!|6r^78i;6nK1)W5m5hF3O66$K2Z%=FmAR_Zq=pXzWp80XygSeN%lcMn!TFY~iesymCmkE| z2lLgJz05Z3wRhHP;2(hozNbt0)d8*yMAtpF3M>^LD1jyvaK`}t&Ennn2ZGv6o9qr` zm`}dujDq|W=ea4)qm<7Roft2%d|DWtZ9njB?w!7H_j`;)Efz}q32rrO6P^owIy>RE zSo#e`kG00r+-6x)c`y(2Qw}g{kM4ur-{oMEkUvz1hUD2C!e_df=<0I*3N>DX2xD7O z_;x!#-wbt{u%_QTlW8S)b3F8WXF(|5Nd9_8&jjwjrg=U6RdGNlvKhGWD6C(jB{wYU zlKpUNLwq}fI}>c!A5AFv_+{S%bk?MYn5_wj2f-#am-jpCN}rjEo<+rKU;OsdQ=O%A z4m`oiq!%X5v;YtywC=k}q!s7i8< zoy{<36?Xsg@k?s1N#g!L*%7@2hPq8Q3aw_CyM#eB)D`7_PwQ-DmE3L;cdnSpY|0x# zwnkeDr)F5we#oi7aJcII_8Y+ejY!(F*p$&e$$Dim@I?Q-{HT9!ivXaelQS&w^<{9L zf^C1e==L3Pb9`)68H@jMHd$_J8Hm|RsWZ>ceeZB*NI&^XQJoGu-HtriDTgMSspq^({w#~r9_ ztXja}C|=e;1&E{*DD44E!?$gIC&JisWUh}L8WRhDy~GzxhVzVh3AP@h=%+*!do5J3 z3`24&wfvqlV9Fe@G4j;xbXFF$vwKyNkr}g3$_FsGvLu0m{~b>%E}%GbYX(%r2dHZi zW%Ws~1pmn)+{S`wff>33sp4biVfD+5)van+jQ>a|24oyG87IZM)2MQum^R{R;-3R` z9_(FNsMPgmoYq});&l&SeUZ~y*+UpX^;I0GbcsP&P|=O&vE+YW%e4t>v*X?6+f$z` zRoehk=gHp2VG>gY6XEmi!X|5#)_4YMe7$rGNEgUI|I#!z&V#k4rRtZtpylCnFNXcx z`SJp#MXuQ=8HdZ1Z1y1PLx;p}rA&g^ufl+^+ty(uWQ^udF!+~80YvR}pE)7Nf~mng z4`%LKc{rF)gSD+iVE|6yb1Ei>XxQ3VnKUs`IsU#&EQyIR zY>-YS7;!B1QJf3ghL~6H4-5J)<^A<2N)&JY_jdtc_>eq*;gqKc9ZsMfX1U$$|27;D znvF!a`RQ`Y#RkOgmcT}^i+}*>KVHGoXq);<_XrrI^|44XQ3e~peEjEj@V_1ja7zk( z1FnrinUFFB;4G^DTKR2W_~&hgrL8TAXl86*b{3(ui%t_ z`^(>t4xAtg#Ze}t^33$Zw7)<6w-r5OeM_x}%pp^PN_<7wKl6h8PlJ4E8-g-x$1x%I zioC@B+*{~_j9Z&i{@PiJT}puE+o1ga+Qk1s{=cdB ze;@x>XMaeT|IgUYQ--(AqtvGVviT1rbrIL%C7Q6kGrqhrl1rj6S$ZCTjCgC;o55{% z;AhJJ`Wgbrdyo^S@wu{1xxJ2hkq-0b_sxcL8=}8(F*>^Klyvszzx)~CcA<82MpftD z%jMGs8~^1&5ZhZKoXlsBKQ0DbxMRvYZpIArA#b|9kOR0KnF7%HsN?$e`j7B0^qRif zDNs~=4a-xnqaW@l5r{0~pOG}VfrG^NDzWGGpYT7RDJ}SG{Cbmd2e_a3XWpGa`;)t@ z|Luc6Q)9u2jvvB=bc)_x{1=Fa0+cAzmr1{${*kImOwXQpW#SB zipm?1w!a0ONWD_yZ%AAv{c50?q+*~@ zhrU6cTHYYVD2q``%_@_BeE1b|^Z4{6pyFlT9rbYq#MQiC>y1`}CSvcse1AZ}8Y-F% z6Zm!s@#shv)!Py8{~7V+KO^ShIFxWZb1XOk7u{-;oR~P{E$m%ZDvIpN_zDaoUY6o* zC`u%$Q^!f5l(Kc@0i9M5GSl1+gvlhSEezZG{>8do+%b#X=w_AdbIuRUFG1F>-8+kf<{j^*9)$$4r*2e0FU48qed zwgz0Un#=nY{tt8S9S-N$wGGE)5~LsqN%ZJFf{5rM%IHL|AtHLBw^34vh|Y*E7`^v8 zq=@K@UPtuN%P`DfzDs`PdA|F8|9+46zi}LweeG+nwbxpEt#h55P?ag0sS1K~!nsd1 z?TWgk>1*^F3E2<5fwK*c{nca9)}rdB>d-~u1yNWpb$m?`hO)Eui*)zasU7D=z`>a) zaEMrqZo>}4#D3nvgp)NaA%`#WqMHVf_GO5#fEziqaGsd_cWst26dbw0x>}JG^Jrq@ zXZcQ*_o{aW5uF1Tf!s9Pv7T`~VX@*weVMkia=P^fLm~RQe7f#4qD8~!p}N{sRPmS~ z(YC*KDf@-1ia=rtz{RDj;1uixJ8fgRd8x*A!qX-4!ZA1>v@r5DrB@>DyJ-L_(m+-0zuwmPf4;+Tx47VV z6tVE+JJ|?ut-h8^Lh3z)d1Kgl&UZV2po6AI$HkWI=DDi@+GIT^QpXm|vi148&@wwQ zk%fFFQ82PDJN_)MdL)zgn;rx!bM3-KidzqfWXLubkV(ihq%S4h4}{Q6a%sj&p-Jo{ z!jL!4V?o)WYhW6dw!YQ7mWJ1YZF&0aa(6tazn1FCW4?j1l_hQbR^v z2ivL-wtt|RZa#8?!kTfio@4fqG#4-4*i^$Xdu|Yr4NQcxbun1yHNVXaMI16 zWjmaGhs)7V1E+Fy9UyNP^~=? zJBSq6f8iktJ!3n3`uPDQ8rbC&mH<3z@^%q7%r5jN1(1-vzAk5J41&8Too{Ie<1_9t z-WftXU->1V5B$h@KLZk#&(1t=7#&omf|a_&SUXq8mzsQm6gQl2cmq^IF?Y?E*HGxu zJrJA6J_Fg`78b`|9+@1NvFOk%wmEjwc>6=!3;UJ895L0!r0ZWUma;r7tdT$8DK+e? zCD*QflDE7Kf)hM*&KJR^yl&3}eO3p$luf}E9YnRa0MDacl@RD4ZC2)pjD7GSzLUvo)!?U!6=EOxzWKW~{V8Nm5;k_ZU^M-pG~-+)H(Ay))D*nf>1{N=ml+^F_=6s_2^% zi3syQW7!Yf{LKT$GhGe>9I*1-$lmb*Wtc&5+E_(*zqTJ6x?7f0&f>Bbk;PcGur9FM z$Qb^e&b=R~$o7|QRzmmrLIHpb^N!VRs1aRAg%N+SEpMflKAqW{Hst{-*^LPWbqQt!7x9#%_?_2tPUJSTS_eWHF&)IrzJJ6_U}#paO8g+Nied*>|7#i*#@fE zR`M6s=j0&Mx)D%C&;BC@W2YgX0#p^t5?7n9!cod+n>$4wG42Tp!EJ0r8N>Me z#R?#|VGrt4iHhE0I~KDW0Bq*TR+*h`E})(aMm1@2W#{Jib#*$`=9F?>oU=@x$-0Mb zLHNq|Gr7%Fo;1lkfa{MM?RtK&TvTuCtPK=A!3!ZvFag4yD!#Psoekt?r;ZwDr{x-P z0tsB-*>?!kIA|!Hbc~m58yIK?z`=l=Pj1#%TIoPwQ*+$DK4J z&<8X+8Hr>wTAO|!$B#rRcn>Bd#yBBLsvQtoRiIb(Z!uYair*se^_=)sgf60@B_LA} z=vhGiu>%>{5pJ*^Y<|zcf9HT6?S~{q?jmnf+S~$5Dw5w(%vYEY4o(|6o61=^+)yg( zjmyM-lu=m_-Rv2r?ygQ-PfJgRY(iIsjj|c+x67xSgZlQjPgWhL-7sfN0HYBhEv~;- z7tqi{(&?w_M_6mD_^}&zJ29F6g|EKzsYB_MK<6kf*&U`(5EVq&hMKP7=d_{E!(Ix3 zW({_~wvqGK%5Qe740Lb*PNvK{cQnuc=wLk)v}GncrvrkGg`iZ7%!HhKp+QzClsr(Z4$%d zgR$EQLiIYh$mO|5j=@0=5*M3fKj;Y-mJsYG8fFc%w=N;Y*f~o=Ax+AnXD^(~>djfx zI2l-_p6u0>17+Lc%9$Ky{fk!#0g{g&={L&mx%W=Sy1lQ~X?P1es{5gfN-HLWy1Rwx z2oN!SMz}O=E%#Gj12xOEdfAO)9xK zJhU#om&-FYWZa~huCx4>l2{d?>P`v=%yX;|pAIs$7v^&97!{irz$CEAaot14L8*P~ z`KcP33mp&}Xw9`mu@h`8g9CD92og!7>!`f4pLj>Fe8NNA^Yq5eB3-&4=6PWIsU!iR z^pTMTKUGvh0P|^hb*;$ayl{|UVqe@Ws}ra8B&*iE=MYT<((obLzZ~Pysi{7$Wc)bG zRMqlFhpyh~J5tnOE55 zyFD+()`bLn4vfuC9A1MPsI05TOOiUW)}2Xdj_uf6f}OLyEgqJC4)s#V`bPG`ws=FM zq=W$Z&|&M&$j-nw)41__C<&{fn0{AE(f945T~s0@UIYvocSb5SHYZRTZWP>WzV3ZT z%*GQ$m*2(9hAKE7K|YJk5RmH(Z8KT?NIswg)QcMshdt5ZIjwxmQ4SV7bL$0AS^Jy_ z%oz+h8jDroQl;{SBhKDo*5L+4D^p+9Z|CQ&mxkx$2*bw2dsFO57ZGlo4E7duzIFC~ znKNz8*}sJ?`lHS7LUp>nEJ|;|tp5b3u>GcpZMQ>|t?MkCRCz=j@k=+V_6_@H=TGu3Sq#i!weX3kI;!@@ z`5qv;OBQ82Pa9O_gUXdj-1_3ZvQF7TdEv1gMq7wLRez{{3{o(-EdO}A17dJyc9(`J z&R?svC@#6Eke?GBaBWR9r_`#qg@K8AcOylPTGJ#aUcHU(DL?$&$Hz@t^$Dfp^M(C~ zr<5$3aKsW$gha%w_02X-IR21cIdY*?kgZ%r+h3p7;b+$Az*p-9k71 z6ZV$k2RE1ITFXdJWjbxkFINcXKXl{Gu0m_}_f~v7-NpQd@SiD}a(q0qFXr@J_%l^M66^kZDLgLvw)2Qrny zzS{=0f*ESdKV_n3@og}aroI2M)wYty)6--eqP8N}Dg>H1^($BqBDOshLsUz6-oBC6 z+@TW4WO?$=R5}>X4Mv$fyEpde#k7rd%9*sC650Y@ntQ9LKn|A2ZLi77sB_%#MoM;1 z`mxFqovSB#Cvmyt!Vj-7CdjTjyNqzWWmuId2;tMt^?UIq4K#|#B5vB&r~D3~Xjm-t zOI=_yF0-5AvgRpoQiBUgd|_Lbc;`w%VO(2mhfWECDLY`I-e*k5?KVid;8pF@^&=y$ z(kLEti!L4C2_2%N`&I9)iajP6AlubTC)mp>+$lj~(pSK)KzD*ShT4JYl7$TIt&4{X z(jRArwja>nyC^Rh8kASj>ZYM)*I$M5Of*4k%#Hdq8Z;Z6^&*URwbhu~)@#;gkvE47 zIz4;$my*ho0^MpEbG?djc3W(#Xkzs-8ob(v#>j-jJBlT|EPt!)F z-i5DdNi~@k1elP#zM$}%K73d^hLRojPTPKNAF6TvEvV8Yw~JUfW{c&CuT;~JK|z-r z8_FUp7X|5CUz8$Hbv6D|Hkl?>OLX2_XcQLR;(5j8$t<3hD zZ#u5z}^RR?M>3oGZ z=4T{Z_gQ!{Xl_)iXBO?QGOb{h*;bseFYn+39(@=1Q&D{eD(d`}mqYxX|5>IW2+{gJ z4zuP$GeR_1NR=iYK=?97SP!xhP;XX@JQ6Ei);XvLg8jf%&jgAD&5tCF%mX9d{-JN4 z8T-*nCFe$r*!+xovb&E45*(}cO-2n%C$Q??Z^YOWOq|jp?IXrsWlQUlZ8qro?ez-W zN3ebC*@?sztQl{J<@b$`Zeavnwe~rjh+=WL!sJ?bqgDza4y&FP8C`qp-juOCR%SRkZ)OCkDcb%U-H)(tDl^I*R-JRY zvgv#fG6s1r%DIXUAD1!yq7NHn>YUN-cJ;A$DPm}yMZ@FOGfUp(JMws2&;`?SWj@GN z#CD?Zi*5xbBf`2Za>C)QkaOox*Vj4b>~|$kW=zMtR92e#v=$chfz<(27UMM=!sS7= zvr$NhogOn7Ww5VYwO4;7K=EZER+|SkkazQ&+)`+T4!9-~rKdb#u;xGmWCn>qPW1OC z)z0XtceoP^HQHLa7`W5;#D%=>ORMh=@0dU&RIo9Jv7-qPeuwVe6_qkB(V!mzbrmyg zo)yAw1x81A+D{+tr-$GGOquvj88QXunG=2Jp#CZ~I`@p9J4cn)eJILQ;^kMDF7x`} zX>3oIMFPXmu36!Bs0|04|2J`dHRE@b5oxpBP3L+XPinnC9rMr_8w-MWtn(Wff0-qQk%~KfgfKC|09n*DfkzwYdDSv>N$K z+eL?r$WwNd%E7iy;XL=QOQJJ-%Tu1+M-tog(oeEvGx-74{El_(e&|`nUS2Bcr&K$; zv|yMJ7O|7geoPRwc>+q;)3V-$Iu-J=t&Vtb6Uk*7fC{KEVqD4bw!@7<3&IP6@mm}W zQ?73fx)HZ$%=T{VAwTA2<*uTrA3&_@KDU8*htMvY2E~)zVzA1>9Obk}~0ug%=Zf*X+* zmt29L2K3xvT^H1}q%E1JbI_sT(6Y92doM3#^ZS(%4`{_e`AgSD_34N3Z!r*Miu|Cq z%O8KMTx$P)kxD}ZuMsI2OOA~T;Pd(DLfURSaO%yrZ79m0Dw@to9ImH-O#3_kbfZBK zzH7rT6Vu#+zpT{?JE{KA+Sj>$R5vV94r7||_CrS^82~2ZN$f?7tXoX10JadA!GaU> zQrMe>f`pcw#-_9)348jE5yHL1mfOFjz#*!ZOz*eoPUCgRVzLALjmefk;uRT~LHg9B zZ^Rkx6S}xP>h;PiU>NIMQZS)$8geOcJH-O3uqR^96m3#^BFAf(eP8-}heU0_w|7ia z-WGNq1+{z1m#Wj;UpNJ`f5`j!<0pZ@6;72eBv$azrzbyjbU7@&eD3RM^4iz7DSq#jco)%vjxVo^47P8oC8=dU$-?6Dyzo~i>4M);mD?91 z#1dz@5{_0C8(J)Vs$pcOZ6orQ_G*p*4Z#}v*hZ9NRh03iRp`rro;@-E%<-zcCW>IV8PJqhYwI)`rLt?bngT<5A#~4^6hmhphQp7xQ@+m#BE4UD zoYv=0K`hV%f}Cr_%IWPGEZLM(RY9-Kv@kgrFXhhHoyjYtIHVK~4{sINo4V5>MCu#! z_(mR!mRNACXSq~@WJlFX_6^sgRdu2=#DeP(rOH}zZIVL^OVzk;TBSxQgK)Nm^bS@5 zy?1*ZZhXph+cy(a_w=$~Emg~>TwAP(o%9O9O#LEbD@tCMPIPR29h;+`E82V55J{zb zG0dVdd3SnRIKVZFas5XKvjGtCbdPJUWi-Iu}p zsXOXs4xfhQ_x4tvLpsz(Wn-nW$Bi2l0KDx!(Y9{Py=)XjY^CutmULGVU0cyK*ddr?yk7HHsb(zy= zN^+pML!n*@g`Jxa_5LiS4l~q`KjLIEO~wT_NvEn$FFQQnKKb!LH)%>U1kyUXe^_Ao z)GF_%@G52(`L;??8c>;ej@PPD)(D_h^oXMz+OaukY7S23SoL`lEC!|Ef_4nqdZLiT z_1sgE>gz4mT^?>`B^aUDWQT~b-pB$Ly%*bL3GEB79=@(i1hCGAm#S;WC^ixiV`ND0CIvAZ>Ag5>5 zpC~$3e?2)U?Ud6BUS;Ga8IO666^ji0frTpwE!pj3zE(Z^ ziKmf?0U2-NHwe*4L&e$?Z`rOc@CnzDhk?22N$eflH}~3Gj-IJppvVtz^YwWDSVWle zWpbtx`L*8F7keXr7Hm&8@80;2K!Wqp<+pGc)34pDS6u{Lt1Ozd2}Qa||ImScckkENU~c-7l9P-WfUNP>vdSj>^)x%;%} z%llJ2kDm`d?^zrU&gkw;vhf#pP1<%N_%2K{Yz)ZAaA3R`YRB|+{qn!u>8DmY9!bt5 zuwCKk!2R9yZ&?qpG)PY)n4ZjH_;C3FVP%ii3TfB#IQX2)KUc`Zm<&E-cltwK$x;f$Y?(2}|DAQ?gZGlL(!|$4jT&KHHSMRdOSx~5IUk$An)_+R;dqWNU8TNpxl*eG1tXa>~ zp-3*lUw_y(ThK8CGETNIPSaF|GsSsPku_|#T+U297kxjxB$+wF_;`wo^!-0M6F}F{4_TyFg19?YwVJC;y`vP{Io~Rel(IXb9#Go7Aui#Ya zVB>L0uiNDo^~Q0a(YTO>LVbYn^g1cX4w9+zhLOQb9jdM;c%Ep7e{`XdP(NvPgk8RG z;+5TVlJqkzmg-S%ecAZ;^qRwwo3wfd=#q~wA`0&&OMh0cS!>F*XsH)1i|vr%>09S! zSiXjf&osOa6lvedhS|nFA`;G24Edayw=v5>>fCjRFW1}aNueV(w6o1|K`L=_+E*=B z#FBi4ypXO!#`@AY=4pjI8ach!ZjNK+O1u+>8cqx}wSOPm$|@(=fGs_Mevq(U!Wy^S zQ0QPK^=+}Xp8S=}wmLM~=h3q28RuZCeq#SEYY}z5!*78j)3^BXISVgMvNYs@pvzZh z0S*fmCC1O;!VJf|Y&H8IA}801l9I{!Zh8&ZmdVLB%~0%QzmR@7HoPic6rf(BEwbSB z3C53kg!ul@cYEyp;#+fb#Q6I2w1b+ht8n9w3*qsxOem_bl*WB9Fp0s}Vklpk?Y|P~ zBFRSyv zGDb5F+I=e3GPCPDNep)cHuDSDi27VZSDWcti$Q5VaXFO9D~H(zJHHJ}CXhPm(V!9g z_N#3Hg3Ex&5!w1N_EZ}%Jc_z`wa=k~d& zcTJp?my8E_dT6_VC7>bg*$MjcN6$dUc}7k@K3b1lD2 zw$&xGuDy?8ayeozz^vrpncvz<51%{~eP1Up?)_d9$STVT zwpyob^(@}HCN4(z%6rqDQ+#f5mmW{T}(#3ca;Z25w)v+y~+K# zqx{QO`NtKa6K$n!G1OD)mu{7ke&G(U(!-y8W0_VsYkluNviwl8EK!D&$m6H%qd<<&muug|vv3tuPteAaCcdrl*LQQvn$lSq;`oB1$a(53TN zMsDee>`mxSVx?p-xm|*VV5@PBgQRK9vH3%bxOC0~kNujF;ls!9e#lnTV>rTJd#EMx ztuHq7F)_dr@@_^)S9J5!2(_x}Oj^stQ|M}-vMBZbxXGS-bs~iB96dy-Tr;CK$-nFN z?!90Xcgw@G?>VQ!BtN`hGCIbbz@bIpsF(|&WixnL!(tYWxOI~$)i=*Q-Mw;g0$?B0 zPn_f`>RNTm$x}w;EE>d;@5w;+;uu3r{V#t1nkwa`gkQaO3DiLGVdL`><@e%%YeLI* zx6+CL_&(NosMxga(R#Pi_Ri5{MU=`m?1VfcHbfRZrF~w~gbYbk8HF7MW+mg&+!rR2 zdt5i`x{7LY#;}VstixM*ImVP1DKQh5k$%-UX{6bUBK^%t37-4wHUMj|Q7n10Usr=i zhK^0z6X!uZ<2mSyXl+$;3QepoQrcE6dNv- z<6Mf8Xb7EpiuB6f#r}Brj#2A&%8l&7qHV4dV|03KRH|+=RefDyWIgN%H@Ezy?5W!- zADN&(pIW3vhTN1h+}znEm@0%^MMHoC%6+h(wE4SmvXbg&;8PK@M*7y-fYf|^&~GMo z&I7Yr3tf|bil(nObL$gPOEFc~8=lDg*frE8_(;M(tpwWit2mY{d0yF&?X*1&;Ds9d zR=6|SNrl~)3PuJ>=s1f#w%rXwhpOLjkbY`@rskXN{+&i@R-snv`^vRWT}RzWm8A6= z|K_pLZl{yy4QHdSGutC>E;7<|TbuT*VQ+Wd3}pK2dCZPwn(yjC2ukMu#B3y)xq(^d zRqips>a2OsitzvXHnty$wPx?|YsS!`sXK+Alf|U-%&1PPWfiM2AJm&Pymy6NOKX3< zR>%Y!GSl^0vs)I731DU5meStq3#=~YzZjJm85_XQzy~kq6`qLiUg~VB+|89#B8%;| zOH$FM0=vqPr) zdEJ<`?r;9EAzXz!V)3nCB4nXG>?j183*gTrRJ~$6<45D|1rPxJ9Vd4$i8r5=(xXNr z4|};xq2NGWbwcj-%IM5Q)FwCJV!mhrK!p1x{L90;55M}?i2UN#2)}k$GY}hDQ)9Y2 zk*&(H$RHqyZ+ecniss?Z;LCQHZ1%?loQ#Z38<{T)2WVUwP4+wR>+Wm|hi|KLtF8es zojN}=>lj~O_pNK5dRYQM6IdcUCas)V88a^Vz!sZ2b-Flr z_G#p~PQC7(M}IW~dfmxtON788xCQ^z9o}KJxf)U8vDc32F}ttO{S0-gZr|_DNzD4C znn@Oy8${Mdq@fc`o~fjObvApd(F@hJ4j*muh3ZB^rL)%7A>2z;4_n?-Oy2S0ub*sG zF*FSyPkhx}?lCD6%}b=&DJ^8Ma^+zC+VLhGH4X`MRq0Ue^yIbVRO!$O3^J1XhPBjY z_5U%8-5*=3kMe+t3#UJRx7*XMy{AqD_IIBat57vNvUs3L4Inf8`EiLWGJDRp^jSILZ6?^n;- zd~HDKWLP|Iva*_;0hYUcIXHu>$BT@0*gV@m*_fbR#yH^34@P9lj+dpZs#9V}nJ)zt z7m$b6TN?pJXCIwKPB7VQ{u-hEkrm*~I&3NqcPc;SLe|bnG{&jr*d%9*_LurLE;<-- zZ&L0Q#}ljO)l6L*<>h=8KR=~9&(TK3U}oZa@5U^%G=PnJ@RuojyUvqN&@z!;gK&q- zn%E9>XO&mhnK_B^)}^9i9~gSCY!4!t_O8-KQBsau)auB56Z+yelC)<7Zc>r#Ds3#? zEU?g^z~Co?CKmU)hcHu`gS0rT?{b?(Hm!rYFxUBLwm+Al ziwJdp=l{LVHsqmYUpG&iTQqAp}1lV`U+;BR>~#D=u*NmbS9i#s2W7_z#7XuDg9A+|5JRugj z=NbGlD6s&5fgrw8v&(?eN0z(E%-K(cWw1M3ZXnadQnEsR@n8NuHS^|wt%{TF7>yg* z?$MngvmCd)P4MXYJK!D=+KyD$CKWq}*HKgWTvdXS?X%Vq^M{5SYHd|;MwZuM@>b0rT9&B-Bw04~iw(|+62eYY`9QR8G*Wwg85xSwCZ3kV zVX7Iv`j$|=+`s0#-Zvy$1Kj3z^k|v2D55;Q%|D_lV|sVQSH4i15*5A6h!h`Df&@8H z?0BFpV3)nje4RSw=-#q=r8KZ9a6cRYlwHz3Ts+VFEK37;q(8d;`*t;JW!iziS(aDn z6pwgBQ>|6%r~qFsyJ%~=%Y)^rN@CDG>Y$4KM$)@0{@?(q=m8O66XxJzVCH8}z{Ht*ff3rqgMd<*pTlT7CAxM{n z*UO(NBJg6}cmO!`V2kCaB!5c$`Z3OSoBpV@H7{4>Q%M0yby{ZP-$>JfM`F7WD4w9w z?k0$S^W*ii(%Zpe`N_6o-mr_n5l^GXLg3gD7u7{}Y1@x^ZXGGZ(xPWv5_%}%6bo+A zoh}g>#rCQ3%3c5U(rLR8B_Nm%VY4ZT721rDZ!p~U*`!3&B zaze~v>Ve@mZ_L6tSzK+Lzh?*oSng%RtII7mZPv@GRpM$^0}9gcYZy^*~E z5NPcDanYkrTie>i*}JDkSpZCMW%F}857-#6yvFqr80j$EM|I&-w!KiL(>xVKCnr1r zB<;QaeBB6HwoaZ%LPc30=ExxEqxk&1j&dTv&kYoRJ#i%VQiXGht=B&rEzX%-V zp<$IIru<&yiIPRVgzzc<`OqF+p1b8CRz7tY6w+8n6kfZSnH-tKLgD%IMNq=;LX3rU znroP;xZ0k^d^(brefy!76}V65An=Ep79GflV&|zTCz?DaAojhIjl}P_UT3`r49ON8 zKKfKP^d`v5Q?7ASP=fNn)zusu(_-$gbn}?6$+-T< zH8Af;Z9eiuXBLLL$G4k-n^q!QCHG{PD>EK?Tt#@? zm@wRlThBp2y3;)5NFY?CzGFBuicMuQ*n~)-to|RE*Xr9LbWrJPy-k0m{`Q)DsIUz?h_R-CCWLo zzDm}&V4qRO-6?2Qy+NWtdSVn3ssaslmq2&G)9Wq-w{d~`oTT=4_mL8j_qm?Yk@}LB zh)i?{uzN%4=VxmOUj+_2R0uw_4tbn4yMDf>7k8M^yg5qB(2n{jsL`{ic#f^isN&BN z6fZxwx#*#~bLb$@j%`0=3LF~GdlS=<;A~2ob>k?O)KOSJ74N}gyznmdGfglAsm#+MLTj3vt!3(%YLL2=7p7{dab z8(zTnYFk|nDjr7|Ug1pG$V~83wqP}@og5E_$L(`MTFveG%k|IBjvS8Bd2atEN@GZu87bsn2rudZ*MChos$kI@(i}gHR z&RJ>OA*_let}<1pazw$ta^^7Z>Nc9@T}Ws4IBD;yZ1;^^IPbs0skePUO3f$d*!sRc z5`ap=4oogx9?lR&QbEH&gu@GcMXCHN|*ZhzGCEg3D*Xp{1Z%HTcN=t;o6o9WM( zWCSRg=E0+|0;&&qGQJiBtXgH)>#J2k-0N1WN}Y^VVMjBHXe(d?;cJ1?Eji3L;9YM{ zgT)RkoVC5R?o39?$hRwYsjND62|LE>PnNjF!msD=T$zZGfM3=+R)1q2WBEV#^zO0F z{eZq@Z#)}7(k}T|IBOXg?M=`wmL}pNV>L}%iib0x!CUeLp(K9d^;-)RB$(hJf+mg1 zHv5c!CvqKu-^!`kl-N46C_WSGA8Hi*tVeomWL&13N{i6PJwRXapqZ96LfGv*EKu6I zDaf|kF2+Ix;3v-4>2GMaDAlX<>d4{8ttIQ%`JuaxaH50vm0$Z2!hsFL*_MUj)(fye zn7T(rPd5bWKQyo6EW_WTG<37yFeCIpM&Eb(Q-|BFf5!TESY`l__p6E(KEnE{LE!ZB zOy7jg525pxu7966|0$~uPA_sz1+RS0^xLA-ED!t72LKW_xwifVf_$=WY(UM)#1~o& z>G^e4|4#nT&wH|#PfD2B4pPh~HHOP#$)^AV_Maokx{yjjVl4QacvY|trcz-H|J{_k zDn-=)f}n0Uq=LIyxF6h-M}FbIhH1M%)cR)21GtY;ooy{(X8IKV*9~F+|JSjSc-J4_ zM*47|6AMmCl!kjb{%fEM;L9XOX=o+om6#lhEZ1!@E!v|0{4M}`ug0?DxQT7*T!#!x z-JXHw4R<>KABIw-s1L18V>Wvk8xYeq?y7L?2oQq)E#7|zWmdMlG|{5_XkB7RaG(N9 zHv0bde?4;nq)W0M@d@Di!Xz)s^EMon{2I)KmW}F@V{S4 z!8YfW+p6f>;%=H15P5if>;e8S!CeRzry5sWBA7n{`k+gkQu-R4KLVW^|9hD8_5;hH zHhW`2el-M1>i`9u<9|Pqc?qPcmxh8lPs`6d{hz({p9B4e`u+Df|F1l7$3(H@!UdTC z6$QDc|957oB@%2Ce#p3T-gS$4+vZ2T{5J2MZ_D8}`{_D$Q?6IyhTl+e{@=~C=R)~w zsqS;`m>grVLC(p~=-Kh_+>0zO-gv2^_2)5bq$^F^^||x=4Fq8cXhiwz6*@psF}IA zSo0j!gsS>L@z1-8f!1H!5&DPcjm4I1f4z%o;+Er|d*l90c>gZY@hVsue|~{erZkA1 zvwp6ijXFe}|5Yib!nY4Bc=bAm>0QBs&I0w7|KJyAowDmm06NAd_!CMt? zWyb)vh6`S?Tg}fK-oqSJ*J(I+^Hc-xN(F?OXR`lqdlu|Sa$=hPa4;^+8kUHd{yrPs@7o z`(b}m(NAZ`JY%g19m+E7Qu=qG?-XxC;13+T{1sH0SV)8O9NPhHO$* zjlI6O(W*iV+=J}Q_T=11P-_Og%RJ&>3nIJ09D~-f9;Js=yC`hhd%9S?21vF&sd%k9 zfll0nAWm-y)3u2q3x0km29}{32p?v>AkAg=_b94B_vv`9s;i{$JY9`yVe`sQZZ#iR z=}MZ7{1Nx*OL?J^4W0?Cevmddcv+#XOx7<7LydNW^C~y7@$!78RSgt`R#iLfa#_aRk?8fx#~C#GYYP>HmRF!&yZ&JWQ$@v+jK}5V8zm+E%?=MWW1ey z;%k6DL@GhN5=sS19&csK2e3g~G3q+~7oz?)4VBD03O>K%PzYfRqf8W)4k!#Mh+27iRnR%xpH>k?Py1})g3*2ZPB$1~ zXRiuuZDmx}lv=Z-H7X@^m!>s8{`(dHP*C>k+my3-Ol&6pSR4$>CZW%Zh|`cRf+DCA zQs_BDc?cZ*ZWt*s*wMvc5+VYOo+k}MpqW@{n%9VD;&F2L0dJ)}Q^Dz><>NfaYXTep z@i5gILDsXjNDLLrRJ8|an32IglJcQ`NKC+@t)yFAEVMs@{Y=*KPO$p(S8qi2 zphA7i?hFJ?X{^AF?5bR5;K!xdED}f;uEH&*G z-+g_MdT+qy=Zz!ha;9USzUiFjC^zdc8H&$98f+4+GMUvX{@pX&V?#Hmq4l?|+3}G; z0VkX;k_9(`QcbTX``aT{%LDp%bEEEQa%|>GfX*=E6Z^AB3Iz>GH?;xP!?bkbU>%YT zHl?yyMFeMv(^=udVL~Y%zltPLdMJXtgX+{jHnPP{g=m2nutMY@Ht^|7TY}*eHhWs` zt0^X=Irk3sJX4)H%2vghswkzXVLJH zT3YsYwczNSYL2`gF*&1u-vN4;Vv|X`iDLqwBmQe^G8=$Qx`a?dhkoC6e|V)xB~1(J zlJWdHgzkCxp?$)nT{!SAs!0z8ZqP3S?(r0u?Ygb8Ygj7t7|K^Wcd+TxfuC|1I|Ww* zQ^JNHDfA)}Ua4*SGPY`=pg%QGp+nN#H=??Gz7ypcfA&B~8KoklnCv^qT5+f6+~uhO zw@XMTX&M|VYDQ;!n*By9&}-)c)AP@bJRwoQD-D-+k^r3Go5`58M&@X`;E~1X3~?0O zV8y8oK_1;3){$TzP)d*OIh281v!tB}WZu2?XWU^3pkMl_6ErkZyAhK%bT309pCl=6 z-oJJu@eXjS__G*m8Nj?6Pef82C}r z;%Awr_yv>mD8l31hsV7@*gVmk%=SE1OwO=n<2s3>c_Fj=t@>XjjgoyiPZ=I9tC)f0_<*$(Klk)@Men`u0F&g1ySfW^ z>G+0l;g`G4SR=P+B?g3Cj8V#WB22B-SQd$Dt-r{eO_Lc45(9mnvOw9E+*b>B-`27rf1%PpB&OnLvm5Fmwyst`-$D+dKcmI3fodpr_WMKG;ui@uD-c1=hq+O? zD6IivPB0?NF)H5o&oS?_1i-M+z}lAu(ukgN2zmJpkg_19y>px_Ch(#C*mJ&rzx!oe z5T}oc)K}nI>cb||L+AtO+cz@oL~Z(&Gh$yEb0~Xi}P%W05*FK-SwKfC(Jk*`WlD(k>>`A1DYp5QY~lc zqvxw7-yRrK64y&d75UXY$tHl8guATN#OToF(mA78u+RA%#ePe6Mg5V=hr(-u=Tfmz zh)DFH`fwPPZ#HwL&LenkQ+3QX-pbOFG%L$F#!!6V6q1no$~ZJd(ri(LYT8^FuCeX5 zN-5C4b?yQUF96GUsf~AaU^UETxHNOX#7h)V%`souhXYrFS4qO@@!Fk;I^_7%Ne7Sv zk1yx6wzzHxH&y48?#;Ng&{Cz=JXpeJ6Am0|2*`Pv)ce*=Bos8rl%8*f4I80-Ci3jf zsZ-C`$l5YeLPbgrc}I0vc-5S{<*9EcJGCJcEDxHXas^z;kw*p$@+*J#x_78HZem!~gE37f2zyl>? z?i)$X9p3iH6?>CZps6HErM$yklE~tgPx3Hr``x_)H1Rmh*9KyuM zC{?{?0W(s}ZF!0ZvLsM@Zg}otTaYN_yn{|7ES_v3F-I^#AQmQ&p><)%aM3p=?>TCH zLyR}SyaPg>n9iRzntpYr)zHIVZA}8&trBxW+N>?0I5k7qChw8S$&x(5g3p}u7{Wi2 z+5S1XF!O@QW5i;Zpyd1VYwWKAZ_+*sbZ!}WVUWE2vDMhOP~=;-^Z(c0SB6E|b^i*2 zfI%uDDJfE-NQZQ{fQW=hN=XhiL#ZI$Ejb_!(l9cBG)Q+2(mnJD!!YN@$LE~$zux!r z`E>Zib#b#}?Y&q2)>^ctzTQP{hPIy%okb)fdiqmt0IIV)(+U0vi4tF&hFzQ2E{fj6 z^e#&_#Rs(xmirhn(%tKsKLsLV=U>SW_^c>b-;p$SsrU`_o&m1YF8P%7xFY1e#=FUW zjfuT!6P6vADBU=RIDu069hZ=bS0Vj_t6jV!BkdrWuN`3Bd})A@lqi88Y&ef(s(h_6 z8bvpAWO^hp0|jyM+vDMj2udgf7hA-fyZb)KezF{aukuePZb{N96KMs=d&o2a^_{MI z_h^ja9rU=IyQUUfB-aQkwf3y>!eus|nK2=ElzKkd_Awh;^43U`do-VihFy6r3j0!W zk6+cF?kN?n)QiGlN#~u{;#pc0FLlp3Y^!-r<9Pm>LrU!XX7prd-$eKuEQpg8m{PO& zGW4~i(Gt_+lh7E+$^3}m4~)Dg+y@PP!K;e``tY>4T)Pu$u`70h{+twa3wW$_A( z{W9kBzh+Me zz@Aon-3dh2h+G8?vw|S{^DH91207l7UNy(AP1`ESClzx_+wf~O(PGr_ki(~&89JKm zNx5?8itYIkQ_K)~`4fvg1*?*B8&pD)l?zR{o}l%sF&skG70zaE%6QcwTO zb3D(~jBDjHL~}wd^SdsucAp6uEVk*5KO3>d*v&z@_8xqUiuKlMc;Otlv_21}+M?U6 z_s(}fxdt~##-UrEzh-EN1`Y?!nxWCl7p<{v5O*pze4cmwe3N(NUS46P62W&R@9?qD zC(v_d^uP-mBh?ryLUFlqxtR_@2-t$2$|Ci1$<8Z}1oW`Sfm4@?W$@n;rb7Y&8^v(( z<;OaF0XBh`!QRCVB?27dehCVi7LUX@$em&qj9=B+=iy2{P^ZaxdFGxQ>60NKbmmW2 zqIcb0_#mrho z_S=6;BPJ`g3{L4w?Z+ibWxTv8X8oYTG8*G#&H26KtuJa2l*V!LwG|A9p&4xFLAUi* zUQ8=f79w*`qdUCj<}UDs@2UO# zYo~~v)hSvp6pQ|-@}*hZq9BhWx>p-eLzWtv^>e`RN_0+S!&|-Q3aV1MdoXZ9W=tN| zIwMj0wz2c77}4&cwyM$*93#_b@?SjO+e;B6@kz6K_j!@qG5n0My%!pL()7>g> zJSAs@l1u3Rh6)#fC9_fQ%@6_I>KV+z;;*X@-A4}Dr$w@Djfi8e$6Xx5?Pfe&)G%!5 zz36mm^|w;>2(X{2?LeEcP`n?+t}6>MI)RZoGUL=C!9kG>sy>c@q0l~{JDelp0rM{` zp%L~+32XDY3V-hD!-VI@A{&hH_su#X2vxW|WKOeJ_y(-D?3m7$m69a;1kXjJZ@^{m zhAnHxQ_IQIFGE4s;cHin5ACtEcSgaCX%~cN9lf?Cs;o>Gm$@I&?*Tu8$J{j(4%p~0 za+QMo8rS|2j(1_BbR4+X@pPi~&6R5~kvV#KzBG?+MV1He;(AoIEK{%KyGez+5Ms1n z9_W_-rT8>h(q=X>MblGaPJ%hDw|h`~omT{vZM)-gJpXxv3aVkjvb1txIKsl*Ni+4k ztb~u9E_t!f*b;5ISp=y3qN&e&ZSdIN)Av_=F3q@ovfdiH#|)GI%g(}qUTKn)>R&xB zN_B_bo+i^##D^aHy|bL$YKvbrs>bT-+Ph3+OkLWEUdm;#0sSa0h9wR;GJrBm`b@+s${F||cqpc`M$kQhe0?ysW7hN>UGa7MJFVnn$#xVM{d z7|S)dt2mFy!KjT;rOX0*U$SBgL*oG-hVVxj-7ZnF*9Tfq@gmoJttoAzT9#k9ulW5C zL^=+tzXLq7fWjI}XwPfSBE`$PaZkNoc4 zJIIV^$h(F$I?+Hg4m^|Q>j!BTZT>=xdK#dk5=xQvNxYEw{8DKYuHG<+)thJ{d`$@Ab-Z!(gl3C;n{PQTgyK&|Ta{2ECJOfY5^8$5)# z4oO;9b+`;T3GaubgxIs@%CdZ#nv3-3`y{L!Mc6jW62E4*e9Pb~e(^rOFrOk&HNif+m;}`Awh#GP|r6d^TQ|838Feo2B#utCyzvy z$?lOIV0WsZR0`p@zKQ5VE>#1|2NQRBiB6LjRLtV=NTt*(I@}<5IlC2+uU|Sq9JQVR zjuryIv;^C%8U@=-ijff3)@cy?l({!oKm^6}^bE7G%?mj3s|c9wsVxmbkEXe_VuDZL%w`6mpZQee6rOx<{OIqp#aQ?&X$if3 zHyH_$UlFF+W#s1`TU$LuqoffMb~VABEY7%T?dnN}>3=3mPtkG%X8T~ye^pBH$_d5C zqn_?S7Q)T}7)VR+bMD8G^lm^y-aHW0P?DtDcNd#}8M8fQokSGj>=P!hZ_}{5( zqh(>Oo=fDdqBCXqG6m1$+r@9yp(Gphjj*=czy!3w1n?T+13`5_FIC)K+iWgBN759u zaO^P>PbJtadHnWnIY9SVMflURpHb}Fgoxdkzo_3~rg|UPVd=D{D5*j0-H@=uKwiBI zn?9Gm78c}@{7jZp=ld>m@Ydbj2}OtE ztwYJa{dMQrqTN1kOQjoidfO(%W$5T%4$G1x3|Z*?U$6v#v7cxb(tXaPG{gKSEASniXtw@V2h z=+WUU!E)SEw{c7G+@)6SU4=zMX+JQ>8NKu@Z|WJZx16u_??SRRhFK`9)39}hPk7bv zQ0{Jw3t9f~wF2NA9|i%X32AmeB#|Zy1t=15{Vv#Xyg8F-zxHNtv|VWo~Vx4>(`B|2{h^Ke%)d5ryyz;py zXEr{FCJB%TDx)K-=9=FL4!Cxq)Gdf3rgq3$kvBIZu<^>&$}#i9a)GiK!Rc;}dqyk$ zwI|i7vEMQ78!shmRe{^Unaes85i)a?QwFpEXlUJmwi`uR${9-nv54 z%0#`!fR~VMc&t&5OqJ)IvY<9E<@HiPg?J{T_sH5ZX0Em`Rx2St?Kw4ks?Ph+n zD51Tg33M~Y3jUBK{F&C$7I@E>&t?+8itBE>Wx(@Pm7!vx8+fmK2UradxkQcYEcN_i zMg3xK`9-t3Vv^Kw@4_5e9S; zRj0JeS%2Hp4csGs|0;`$`{tBcEF(_lbDtZi5IS1^t^8p4^MV~j6qHI zPp&9AFS~7b$Jgpa5SLRKbPV3COBk3DC%TY$S-)F$YsUP_N3rOEM;+)Y#@e*7Pb=Sy zB*(oBD1?L;oxHP+d)M@e*opQ++@Wbk>fNRTofc-=unzKPsUsJb53|dQ zSug1S4Xb15MBw0ZwoT}MY9o2kx|L2ScivQdid8yJx6~-p;r^3GO@16}R1QJ#>BS5` z2tS!z=qE=edcDkGa-8>%0)G#qrdfh0emg?hFq%kEZLoJF10e~Nr~Hk7u89TB;rg5)pZG@`PrRcEH#Ff^FWA?mc|fErDc0Tupp4yASenN>T?hi4}PwVm&{sLu=c}{a16*c zpHba04cN9Icj=*;NwklHLUv zTZ;`aRBpquyPc7;xvAGWsZh`A52FWEpV+Wi!A&0l+wb%rU)!8fDguC1}?~4*Ji_Ol=C;7gN>!O;|93lauJY-FxgBh zR%xE_Zv?)LlvM0}Jbn=2+xpvBb=T0LP}3LKCNj&XI@k$%Q7Rg3X@{4?;8aDVSZx~fxnC6oM8lsmN%w8WR z$RRrKcMnh{aN zy0JVhcM4^Fj|#mT(mw|T|JYeu%v~U0o&=xqrFOCZXs>?{;HeEE|Ub@1icIj@rfBHYSzZKI#1&QZvPi#CnDLcZe1XrM>(mE)Qk z2tk9nQ#E#N4p-`Q7w_NBFBJ?GSM62y2%>+Zrsr@H#lOeuFwhT@nxu`9k`MQOS7r5h zk1Nmv{1m2zqsTGCB0ZQ35*Oa+)chYK-uHN(MFoh{kP)JZSAg_k(!vec4%ASfI5Ttp z@+6FXVOS2X`#!MsLfi&qI(=d(c;Rqw+eMmJJ+<^}Z;mU@MZI!Y!7V`NVZS=r+U*kU zRgbTB6T&W{yrBF^yf-{IXWj@h;>JMkeoKi0#i>RBhnn(Q)z|6x%vK>X-1KP&{M2{;}9#*CUBkfmq;>kF*8<+?KtJ4SF|<5cUwZk;9FWauw62 z_OnU5vlX`O25tsAx0Sj|n5a$I6=Evj8{Uix0Jv-?1{6_kTmyVNqr25@B@(y|Y(F?z zQ;#K{AOpcs?Ae^o9vyZa#E_D=F?PyNtow->p()vA?K5(J399Tj<3g~vIH-Hv%#4xCo7K5dS5)cs!-=*jgw zk)LlCk5&jG_MOK7{;B<93Xo*1Kwv^sL4O5jI1Y%G#*n^p5d|U$1|aHTgCE>QF!Nqj z<{^Eol8Z~Yvm;!QaeKdA3(&J@BNlvNrNbh;jvzBl!HdV#>-Q^NV;Amu<>8(+y6qC- zob8=!kJJw8f?`RAZ{bTNlaj!$?AZ@Q)tC+{kGpLOgexA*^GZW0FGeWQHi2+=_Vo8} z#RF>3hdiT}d{U1wb6G}Vz{L~*bSAI~<1g0si&eZ?4z{T^d+&mDF}bbJzw&!Bo_Nj* z>(V~B)vmZ6V8MeA9}z^j^;J6z_pAG-cQRMz*gg|O z)J|tv8FYgi{Eh?(DUYZBDzf>2x||tWKyjnt3lj+UUB7hov_cob+XvDlfvG`;P(L~Q zwZ)k+W){Gso3DRYpkB*klE5CERIl8O%WL_@1(ihw-v`MK)ec&jst`(g3khX+cdAnr zcXp}fvJmWK@!bSV-*0$qfo^0K{f+?@4gG;y6nq386%VzTE+I$miO`>LI)o(2aBa#g zn{`84%k{Bcl^?f2`kXHohAYZJI@Vj+VAN9P#7=VihOhom8PWQni*qWjcsZ+j4awlXk3J~ON^G8e%0jF^QHNYmQzmAmVT!nu|ycV$|c#%fu z%TtsDhup9@;hW(hI*iWrN%0od}kAbcZ=744VHeIDI^y;3dtPex6S7Af1-;mUs z5>i?f$k%enhj^iFtO3uj$Vy&R(k}o!ynMmn7g_=jX0iuV#B}rpq*2B?tO|?E{8dIJ zCJAO~u+7<3GnJjlb@`DbAIpKmbF;JNn0d~>?xPQYs11I6(pj(>x3b`W2X96Y?S$`J z-SZUSx8tf=yO-ahZCs8eQpIDl_~s88Ou)@~LJ^p|mg2Sk47T#mYK~KPyaug_ zrf4EGn)T%@-PkF`Y{YXIhIKl@`kVX3&0mh+M&Q?Y*kBRli zcxRtKb>jy3iBLIdly2+#jhiS?r|xx+0gIDn}eQTtg;nf3*xKDZtgT^~xNMSA^af@P77{a7t^^%$NB2gqbg4*ai6N9m|jh z_N5Y2!};a1nbxoY4}KWe#LwN|AF_Z30W)trXmJqIlBcy%6qCMt9*c5ehaMT6NxG)Z z9*p$Mh*Hr(O9b?g8DS{Yy9d_!>z4+M45_EoG-d9GYI&|hthi|e)9a6y4=ANg=aWuj znET0ub@b#fgIPEd`@O(+>J8_6FblGLs=mluI(^(ni%fh^!TxuZIrc5+$v5K?A~F;9 zQhx^~^HCe{Da0IU}Ih!g=H-+Ctx=GjqE+LGT1nN?xM@WJ&RT34GTeBIO$4Q zO^l>%8U<9uBtFjQR;=IXu=b6Fc^Olwb)?2%n{I-T!&w%-e0S>~bmou`?rca)H6txj zss;t!B6yEvLcbX#BA)#kxoNqluZO&n4)t@E2DK+s78n z3225S5{12QQUeI;jj!V-M?3forLruTRorPWL3@i!yhxpUF@lDW%QDu<=qekzP#J`uxwlAqzTRip>#4CRW;}*>+-b$m|N{+B1Y@rx1<}K|_ zss3)_k=Cz85d4SCS1#wpbsP@N;tMpSYE0X=AgF~>`t<9hwxPP^obIY8ZhDca+N(<^ zb$6Yg7P!M=O(K#W!2HFx(588D=bkmlh`6+ZDjx||4*@R`gIZ%cmwC74y`r1N5Gq54 zvFe~ZnTx_n@Wn~Iyyw~D87qrf1{iR_2JmNa&(bJ#YO{d*;X?a269Hp5Yvt@@Uk#O`R z^mj07mkVvX^lLv!IXH?Qb;dS&(?aSW5-_PSoqMMv6mPZjs+n;aMxwtl&cTIWo4bA@ zxB&*yeN{4W7^qnoUlEfD!dT9EM}j<6_c625aO)n&d$y)4?l;|Do6;`qX$vVe;awVa z+;Pn~K1=p49xSTv>Pw5iMaiJIKSo66Dbv547w1X5cjS~FCH;r?*8nujlt$j|%b{>1 ztSnEBb~jVNhS7l;VESLZ3k@)n-0${thFYS=!LP^rfU+Th_^cPtti~1d6c$`zo5pFa6R(I z^trb5Uyh;$^li`^S&ZthKS^hQRLt``@z#uJ_rlYIwTDC>1}7|%x#!3Gf|(_#2Q*-Z=-@M7lhB{REwV4{d%wIT!Dmd0ALwec zQk8fyeg_!p+!wwhMCalx1lD-7g~k7OdaeL^y%{KD#XAH|&4kJuc2Y0_rXgjiG3esF zvU-apCQoz1)py?e%?XaPU=Jk2d9vXIxrvGAlX?_RO3s^$dMm-ia~8!@cVVzBrX zL+FKNeB1FR;du)M253?H$ggY(^hFWLtN)Fm^sUm!w%zbxVL|9Fbam@Q&(KJj?d)=w z$+}M3fFt}+?rlc3i;fiS-1-Vx3LnlO&o2@48x5L9C>FczpOd8%DyWZ29P^{pxA(9m zKnKSYo0`_$xCy?*UGIPSx|Uc#a8bLml*~AM&WgO8UhWpYcfp$u(8ysRrLSt?2vVW> z3AO6Ib>~V`gHY~te?>MRN0DdprKes^l2$AdrF$%dZ-^fF#<92)>)HNu65t9`i*Qv- zm{rm>3%Wkcs?nC(n$!rthz6Y@!P=b{N-C8SQ%)?~83w^1_01DNfK8K<3kQz;Q7?*I+L9;s2Bu7)#&s(cC8IFwPoJZpnuDs=^vz5zvgPA zRyhJY@T)aE1(oc;qOa}d3G2i*J9TGRyW(fRnKn34KPRTHL8ghacOgHC4(*o7IHm{m zJk%Jk)hrZ0_nskZlV(hrBs-Nlnvut0r zZ6M?701F+RvGHuqe1pnWF^*s7D){ATjoAsK;c_D*=fAR~{hyoQdBlmuFc!NWxxgqE zK6v_i;~XkoCmqhS4cXr?|*iP?;mt4QKVwx$2Couei+#{>ylp6@B)!U zbu=b-x*H-~M)z^ft9kz^r{uiKGSdA!l84#Nw4`OgjW!_5GT9lq83p|*53YBJLnOfYTQbo{2n z_mxHlgq3=^UUEZuMUwYKDT+Lpuy41aPv}LPFeGT!_51Y~l}N`a9w-FQGWw|cL^p}< zt9;_2nwNX2+bg;tv>%%fNwDG}^I{!gIy1d}@y0pGeQy5frnQw*dU~_L{Rr^TUQ3GI z>hph)7cJp<40+2p{K7j+(T+C(K!~y4obW=>YxXQ{c0vG){~VYs&fuuHCJGA7+ZaV`g`;4RC2()%*B z#ZmfHGKJ6B`XVoP;hhAUUmnW)pifB5a%>XI`NXh{RxF_uyh)W zn;LNxgSa##T|5ZOAn~4$Ggb&^@YW&ArWr!j5GB8a$zzL%oqB!=kx4!DZgEyC(-ARJ z`I|fUoCS{|_f;q6;T^|jD4El_UeBKNDTCt-{z1=tS6&dNDDp(A_$Q+(f&&~d22#_H zJ(U-~`|JmQ7c3pXYRxr^-|qqQk5C2)!mois+$d~Emu}r^jwU{*Fh*51u=1$aP3@d` zC8L6&!>9C?>qq_u%EtO-OOwiQdC@-XQbBUDgLTnQch@`joBv#pEF(OI;`c?2S;~E? zuzMbq!=6)ftZU=&?W+A+Nsd!}?REUO<!e zY^=KV0b*Im$6UfjZqpSSm9)l$h@&8rjO4tcqBeKkXy=&q zNO7%eri9KGL`3sI%fk=}2WS;WW@G6_t%EPkKwEj7mME@> zVxdaRSJ4HkZ_zG9^`^!TBdSrXX?=Q~1bOhq&0A9Hp^Ody62C@=V<7IL#1--N1=U|z zTrw990zdr1^DLMeV63@%uRmb=PxRCDY(a@a3=6O!F;TKe_u1b|GQ=+5(?i;8wTTCa z&$KF$vf11x&JN)7?*b#dqxNOmBBlwKVQy4~>&E*Zvsa;Ql|_Pc#*IP8pMfGv8B8aj z?rLvlG>M*w$o#VevF>m@-{Ebp5ha+SJ!Nr8P~INssL{Wwp%+qkTs2~-SaiGV&@$nK zeslj+ITIBp@$Xt`aWshqHiHXhKpk`98&0i0H>P2C8hJGyU8-(D^iLY*k{FoNgD$i* z1k3p!9AAaf>~H)dkm z^fLeOB4ikycgeWlVI##`{oO70H}Cg2pD3AW!*h$xzPw=7!Gwv;T=a1tw9M7g_83-h z_-k79PfQ7Tr9VIVmwOmU3CATG4CI|csJ5)LIrtgpK*1SVujHL2HNDMo)1)=j%lri5 z1kaqK$2(Jgi)|?Mz)3p!ZRZC&c~`uU?C9fyMmQT5jB{s`7l)%mQAx4J@5`*X&em1g zcT<(9BnB?`C&&jVNP6+Wd1r!q{1#1y!07GEXsu?x?`O=oe+gCar6umgQa$6h)?EOt zo@=`1EPd)2ESe!(DiwH^xIt96z=g?mtKeI!yu_~2Lh6q*@z3nZdB2IY#ey}nS72^v zCBE3T5x=iz&XKSEetouKOa@YwYMOq)Kg#?*9BR$jsnH+;btF=hf&6VwUQJd zV&O(YAiKpD9h>DtXp-46I1iUTXDJLmU3(w6@g_~An{P$#Lst%6I{jg`1tM662>e=C z-zm=IK}5A7t)PbJX^)N^&(1iBT?{2jLkU(Z#<44yKs`-h54FlR-&yze0J^t0`;6n2R;_~=X-7*PC zfkVr@EGr8#<&jW*1!_*O5l5S6{w^cKTcO0gj0iQ6ORGWjAJvbpVsAmY7Rc2vqWH9+ zuL)1JFk_-i3xBh@A&MxMuNP}Lh{wo^%5(e{*qq4QE&g;KN&gh*xZWfN% za&IjlktacUmxynCS6Mbw+O#Bb=RVLq$(JCn%ScI$bG6L^A$l8EB@^D_yNJl!387?w zoCv@t?_OPT4S4fj7zib};$HH)x@-|`+!&Yj#7uKIOBNQ7fi%AFwJ*rhmrkmDNyZv( z#R=l!9x*K%{1P#&m6Umfl22$Z_=!|*et>Co`v#Prh;QkAa-3_3Wd%b8zJ`f@?atIx zmg12xcoqCz_v3fT>@18W%rsCU|LXW-frv5(%ktku>E}Fn=@&apP0eF0auY_Cbgvm1 zBKN|SGgh`n*i_36ykjT)9yUpbUctL3^l`3=s!6`~ma>gok1!~fL|K#YVN;JMM;bd0 z=-9yCGOdF#yBridSD+H6Xt}H&z8Ti8$A6$nSJBtR^^Qs7AFav_$Y>T)n;`%78(zt7 zMw@FRJ}N?S-p~=54hpJ_Z*my53sfG5s>F!x!ctcsoXy>y>;S)FJ`euh|H`&6_yV{! zca=E*O#}s!UjzLIS%jiR4NXnAddRp=Hb~0R8ug5;`yFgjGB0?VFlvPqu2SfQ{F1z0 zaNVV(G{;5aC;B`;!kM>MQQ<4i@gMp9=hx@aEuEEOrst@v^B*$L8s&@sTe`SA*^~ml zSLKjR?B&~OZ*z&iw%3*A|L<@CsYE;3hZpHy0?OEMdoPRXHH9qU|MTa+U-}d6utczL z)cPd-o5J?L2LQe>BgVUwwajPTqJOlQ|FN|HSjm5G@qf_v|Bvwh fj(m^R7O~fP8djxhY=jT40YA#}8ggYaW`X|;uVdwb literal 28249 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 F{{S@8piTe) From 8ba36f306291e62d7ddfadf1be16a2a862335bfe Mon Sep 17 00:00:00 2001 From: Roberto Arista Date: Tue, 19 May 2026 09:08:45 +0200 Subject: [PATCH 27/29] restore print block --- tests/drawBotScripts/fontVariations.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/drawBotScripts/fontVariations.py b/tests/drawBotScripts/fontVariations.py index a95e0841..c9e46375 100644 --- a/tests/drawBotScripts/fontVariations.py +++ b/tests/drawBotScripts/fontVariations.py @@ -6,8 +6,15 @@ # pick a font size drawBot.fontSize(200) # list all axis from the current font -for axis, data in drawBot.listFontVariations().items(): - print((axis, data)) +variations = drawBot.listFontVariations() +for axisTag in sorted(variations): + data = variations[axisTag] + # round values to avoid small per-OS float differences + data["defaultValue"] = round(float(data["defaultValue"]), 3) + data["minValue"] = round(float(data["minValue"]), 3) + data["maxValue"] = round(float(data["maxValue"]), 3) + data["name"] = str(data["name"]) + print(axisTag, [(k, data[k]) for k in sorted(data)]) # pick a variation from the current font drawBot.fontVariations(wght=0.6) # draw text!! From cb26d22fdc7625c2dced83ac1301b3568705a738 Mon Sep 17 00:00:00 2001 From: Frederik Berlaen Date: Tue, 19 May 2026 09:47:22 +0200 Subject: [PATCH 28/29] fixing test --- tests/data/expected_fontVariations.png | Bin 10971 -> 50221 bytes tests/data/fontVariations.png | Bin 10971 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 tests/data/expected_fontVariations.png delete mode 100755 tests/data/fontVariations.png diff --git a/tests/data/expected_fontVariations.png b/tests/data/expected_fontVariations.png old mode 100755 new mode 100644 index d76529e8e6576a600f7b63944faf1589246b4112..a0899751e5ce9a3d943cfedfc1a8c38b3346eb39 GIT binary patch literal 50221 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 literal 10971 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 R%YVgW%JLw&pE4Gq{|8MR^4kCa diff --git a/tests/data/fontVariations.png b/tests/data/fontVariations.png deleted file mode 100755 index d76529e8e6576a600f7b63944faf1589246b4112..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10971 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 R%YVgW%JLw&pE4Gq{|8MR^4kCa From 89ec392a04ffa9d04d1530e2e6edebc9a92b8cca Mon Sep 17 00:00:00 2001 From: Frederik Berlaen Date: Tue, 19 May 2026 09:51:57 +0200 Subject: [PATCH 29/29] fixing test pdf --- tests/data/expected_fontVariations.pdf | Bin 17766 -> 9784 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/data/expected_fontVariations.pdf b/tests/data/expected_fontVariations.pdf index 6507d29fa74bfffe69ed1b10b81eabc32e2e1c96..4c1134bd04d225a439e73fedc20bbf3334a7a34d 100644 GIT binary patch literal 9784 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 IRawCQ16xK@KWj?Irg%w;(YA=mA!`rbz7U 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