decorators
-
renderable
class renderable: def __init__(self, rect=(1080, 1080), bg=None, fmt="png", name=None, rasterizer=None, prefix=None, suffix=None, dst=None, custom_folder=None, postfn=None, watch=[], watch_soft=[], watch_restart=[], solo=False, mute=False, rstate=False, preview_only=False, render_only=False, direct_draw=False, clip=False, composites=False, single_frame=True, interactable=False, cv2caps=None, render_bg=True, style="_default", viewBox=True, layer=False, cond=None, sort=0, hide=[], grid=None, xray=True, memory=None, reset_memory=None):
Base class for any content renderable by Coldtype.
-
animation
source: coldtype/renderable/animation.pyclass animation: def __init__(self, rect=(1080, 1080), timeline:Timeline=10, show_frame=True, offset=0, overlay=True, audio=None, suffixer=None, clip_cursor=True, reset_to_zero=False, release=None, **kwargs ):
Base class for any frame-wise animation animatable by Coldtype
classes
-
P
source: coldtype/runon/path.pyclass P: def __init__(self, *vals, **kwargs):
P stands for Path (or Pen)
-
align
def align(self, rect, x="mdx", y="mdy", th=None, # deprecated tv=None, # deprecated tx=1, ty=0, transformFrame=True, h=None, returnOffset=False )
Align this pen to another rect, defaults to the center.
tx
means true-x (i.e. will disregard any invisible ‘frame’ set on the pen (as in the case of glyphs returned from StSt/Glyphwise));ty
means true-y, which is the same but for the vertical dimension
-
ambit
def ambit(self, th=None, tv=None, tx=0, ty=0, t=None)
Get the calculated rect boundary.
tx
means(t)rue (x)
(i.e. the true width/horizontal dimension (was previously th));ty
means(t)rue (y)
(i.e. the true height/vertical dimension (was previously tv));
Passing either ignores a non-bounds-derived frame in either dimension
-
bounds
def bounds(self): """Calculate the exact bounds of this shape, using a BoundPen""" b = Rect(0, 0, 0, 0) if self.val_present(): try: cbp = BoundsPen(None) self._val.replay(cbp) mnx, mny, mxx, mxy = cbp.bounds b = Rect((mnx, mny, mxx - mnx, mxy - mny)) except: pass if len(self._els) > 0: bs = [] for el in self._els: eb = el.bounds() if eb and eb.nonzero(): bs.append(eb) if len(bs) > 0: b = bs[0] for eb in bs[1:]: b = b.union(eb) return b
Calculate the exact bounds of this shape, using a BoundPen
-
catmull
def catmull(self, points, close=False)
Run a catmull spline through a series of points
-
difference
def difference(self, otherPen=None)
Calculate and return the difference of this shape and another.
-
dots
def dots(self, radius=4, square=False): """(Necessary?) Create circles at moveTo commands""" dp = type(self)() for t, pts in self.v.value: if t == "moveTo": x, y = pts[0] if square: dp.rect(Rect((x-radius, y-radius, radius, radius))) else: dp.oval(Rect((x-radius, y-radius, radius, radius))) self.v.value = dp.v.value return self
(Necessary?) Create circles at moveTo commands
-
down
def down(self): return self.pen()
down one level of hierarchy — unimplemented by Runon
-
explode
def explode(self): """Convert all contours to individual paths""" for el in self._els: el.explode() if self.val_present(): rp = RecordingPen() ep = ExplodingPen(rp) self.replay(ep) for p in ep._pens: el = type(self)() el._val.value = p el._attrs = deepcopy(self._attrs) self.append(el) self._val = RecordingPen() return self
Convert all contours to individual paths
-
f
def f(self, *value)
Get/set a (f)ill
-
flatten
def flatten(self, length=10, segmentLines=True)
Runs a fontTools
FlattenPen
on this pen -
glyph
def glyph(self, glyph, glyphSet=None, layerComponents=False)
Play a glyph (like from
defcon
) into this pen. -
gridlayer
def gridlayer(self, nx, ny=None, track=0, lead=0)
Spread nx copies and then stack ny copies, w/ optional tracking & leading
-
gridlines
def gridlines(self, rect, x=20, y=None, absolute=False)
Construct a grid in the pen using
x
and (optionally)y
subdivisions -
hull
def hull(self, points)
Same as
.line
but calls closePath instead of endPath` -
img
def img(self, src=None, rect=Rect(0, 0, 500, 500), pattern=False, opacity=1.0): """Get/set an image fill""" if src: from coldtype.img.datimage import DATImage if isinstance(src, DATImage): return self.attr(image=dict(src=src.src, rect=rect, pattern=pattern, opacity=opacity)) return self.attr(image=dict(src=src, rect=rect, pattern=pattern, opacity=opacity)) else: return self.attr(field="image")
Get/set an image fill
-
intersection
def intersection(self, otherPen=None)
Calculate and return the intersection of this shape and another.
-
lead
def lead(self, leading)
Vertical spacing
-
length
def length(self, t=1): """Get the length of the curve for time `t`""" cc = CurveCutter(self) start = 0 tv = t * cc.calcCurveLength() return tv
Get the length of the curve for time
t
-
line
def line(self, points, moveTo=True, endPath=True)
Syntactic sugar for
moveTo
+lineTo
(…)+endPath
; can have any number of points -
normalize_attr_value
def normalize_attr_value(self, k, v): if k == "fill" and not isinstance(v, Color): return normalize_color(v) else: return super().normalize_attr_value(k, v)
subclass hook
-
outline
def outline(self, offset=1, drawInner=True, drawOuter=True, cap="square", miterLimit=None, closeOpenPaths=True )
AKA expandStroke
-
oval
def oval(self, rect)
Oval primitive
-
pen
def pen(self): """collapse and combine into a single vector""" if len(self) == 0: return self frame = self.ambit() self.collapse() for el in self._els: el._val.replay(self._val) #self._val.record(el._val) try: self._attrs = {**self._els[0]._attrs, **self._attrs} except IndexError: pass self.data(frame=frame) self._els = [] return self
collapse and combine into a single vector
-
point_t
def point_t(self, t=0.5): """Get point value for time `t`""" cc = CurveCutter(self) start = 0 tv = t * cc.calcCurveLength() p, tangent = cc.subsegmentPoint(start=0, end=tv) return p, tangent
Get point value for time
t
-
printable_data
def printable_data(self): out = {} exclude = ["_last_align_rect", "_notebook_shown"] for k, v in self._data.items(): if k not in exclude: out[k] = v return out
subclass hook for repr
-
printable_val
def printable_val(self): if self.val_present(): return f"{len(self._val.value)}mvs"
subclass hook for repr
-
record
def record(self, pen)
Play a pen into this pen, meaning that pen will be added to this one’s value.
-
rect
def rect(self, rect)
Rectangle primitive —
moveTo/lineTo/lineTo/lineTo/closePath
-
removeOverlap
def removeOverlap(self): """Remove overlaps within this shape and return itself.""" return self._pathop(otherPen=None, operation=BooleanOp.Simplify)
Remove overlaps within this shape and return itself.
-
reverse
def reverse(self, recursive=False, winding=True): """Reverse elements; if pen value present, reverse the winding direction of the pen.""" if winding and self.val_present(): if self.unended(): self.closePath() dp = RecordingPen() rp = ReverseContourPen(dp) self.replay(rp) self._val.value = dp.value return self return super().reverse(recursive=recursive, winding=winding)
Reverse elements; if pen value present, reverse the winding direction of the pen.
-
reverseDifference
def reverseDifference(self, otherPen=None)
Calculate and return the reverseDifference of this shape and another.
-
reversePens
def reversePens(self): """for backwards compatibility""" return self.reverse(recursive=False)
for backwards compatibility
-
rotate
def rotate(self, degrees, point=None, th=None, tv=None, tx=1, ty=1, **kwargs)
Rotate this shape by a degree (in 360-scale, counterclockwise).
-
roughen
def roughen(self, amplitude=10, threshold=10, ignore_ends=False, seed=None)
Randomizes points in skeleton
-
round
def round(self): """Round the values of this pen to integer values.""" return self.round_to(1)
Round the values of this pen to integer values.
-
round_to
def round_to(self, rounding)
Round the values of this pen to nearest multiple of rounding.
-
roundedRect
def roundedRect(self, rect, hr, vr=None, scale=True)
Rounded rectangle primitive
-
s
def s(self, *value)
Get/set a (s)troke
-
scale
def scale(self, scaleX, scaleY=None, point=None, th=None, tv=None, tx=1, ty=0, **kwargs)
Scale this shape by a percentage amount (1-scale).
-
scaleToHeight
def scaleToHeight(self, h, shrink_only=False)
Scale this shape horizontally
-
scaleToRect
def scaleToRect(self, rect, preserveAspect=True, shrink_only=False, tx=1, ty=0, return_number=False)
Scale this shape into a
Rect
. -
scaleToWidth
def scaleToWidth(self, w, shrink_only=False)
Scale this shape horizontally
-
sf
def sf(self, value=None)
strokeFirst
-
sm
def sm(self, value=None)
strokeMiter
-
spread
def spread(self, tracking=0, tx=0, zero=False)
Horizontal distribution of elements
-
stack
def stack(self, leading=0, ty=0, zero=False)
Vertical distribution of elements
-
strokeFirst
def strokeFirst(self, value=None)
For a rendering engine that has to stroke and fill in two separate passes, perform the stroke before the fill (akin to an
.understroke
but without the duplication overhead) -
strokeMiter
def strokeMiter(self, value=None)
For a rendering engine that can specify stroke-miter
-
style
def style(self, style="_default"): """for backwards compatibility with defaults and grouped-stroke-properties""" st = {**super().style(style)} return self.groupedStyle(st)
for backwards compatibility with defaults and grouped-stroke-properties
-
subsegment
def subsegment(self, start=0, end=1)
Return a subsegment of the pen based on
t
valuesstart
andend
-
sw
def sw(self, value)
Get/set a (s)troke (w)idth
-
toGlyph
def toGlyph(self, name=None, width=None, allow_blank=False): """ Create a glyph (like from `defcon`) using this pen’s value. *Warning*: if path is unended, closedPath will be called """ from defcon import Glyph if not allow_blank: if self.unended(): self.closePath() bounds = self.bounds() glyph = Glyph() glyph.name = name glyph.width = width or bounds.w try: sp = glyph.getPen() self.replay(sp) except AssertionError: if not allow_blank: print(">>>blank glyph:", glyph.name) return glyph
Create a glyph (like from
defcon
) using this pen’s value. Warning: if path is unended, closedPath will be called -
track
def track(self, t, v=False)
Track-out/distribute elements
-
track_to_rect
def track_to_rect(self, rect, pullToEdges=False, r=0)
Distribute pens evenly within a frame
-
track_with_width
def track_with_width(self, t)
Track-out/distribute elements
-
transform
def transform(self, transform, transformFrame=True)
Perform an arbitrary transformation on the pen, using the fontTools
Transform
class. -
translate
def translate(self, x, y=None, transformFrame=True)
Translate this shape by
x
andy
(pixel values). -
union
def union(self, otherPen=None)
Calculate and return the union of this shape and another.
-
val_present
def val_present(self): return self._val is not None and len(self._val.value) > 0
subclass hook
-
xor
def xor(self, otherPen=None)
Calculate and return the XOR of this shape and another.
-
-
Style
source: coldtype/text/reader.pyclass Style: def __init__(self, font:Union[Font, str]=None, font_size:int=12, tracking=0, trackingMode=1, kern_pairs=dict(), space=None, baselineShift=0, xShift=None, rotate=0, reverse=False, removeOverlap=False, q2c=False, lang=None, narrower=None, fallback=None, palette=0, capHeight=None, ascender=None, descender=None, metrics="c", data={}, layer=None, liga=True, kern=True, fill=rgb(0, 0.5, 1), stroke=None, strokeWidth=0, variations=dict(), variationLimits=dict(), trackingLimit=0, scaleVariations=True, rollVariations=False, mods=None, features=dict(), increments=dict(), varyFontSize=False, preventHwid=False, fitHeight=None, meta=dict(), no_shapes=False, show_frames=False, load_font=True, # should we attempt to load the font? tag=None, # way to differentiate in __eq__ _stst=False, case=None, **kwargs ):
Class for configuring font properties
Keyword arguments
font
: can either be acoldtype.text.Font
object, apathlib.Path
, or a plain string pathfont_size
: standard point-based font-size, expressed as integertracking
(akatu
): set the tracking, by default in font-source-point-size aka as if the font-size was always 1000; this means tracking is by default done relatively rather than absolutely (aka the relative tracking will not change when you change the font_size)trackingMode
: set to 0 to set tracking in a classic font_size-based (defaults to 1, as described just above)space
: set this to override the width of the standard space character (useful when setting text on a curve and the space is getting collapsed)baselineShift
(akabs
): if an integer, shifts glyphs by that amount in y axis; if a list, shifts glyphs at corresponding index in list by that amount in y axisxShift
(akaxs
): if an integer, shifts glyphs by that amount in x axis; if a list, shifts glyphs at corresponding index in list by that amount in x axisrotate
: rotate glyphs by degreereverse
(akar
): reverse the order of the glyphs, so that the left-most glyph is first in when vectorized via.pens()
removeOverlaps
(akaro
): automatically use skia-pathops to remove overlaps from the glyphs (useful when using variable ttf fonts)lang
: set language directly, to access language-specific alternate characters/rules
Shorthand kwargs
kp
forkern_pairs
— a dict of glyphName->[left,right] values in font-spacetl
fortrackingLimit
bs
forbaselineShift
ch
forcapHeight
— a number in font-space; not specified, read from font; specified as ‘x’, capHeight is set to xHeight as read from font
-
mod
def mod(self, **kwargs): """Modify this style object to create a new one; kwargs can have all of the same kwargs as the standard `Style` constructor""" keyed = dict(**self.input, **self.input["kwargs"]) del keyed["kwargs"] del keyed["self"] keyed.update(kwargs) return Style(**keyed)
Modify this style object to create a new one; kwargs can have all of the same kwargs as the standard
Style
constructor
-
Rect
source: coldtype/geometry/rect.pyclass Rect: def __init__(self, *rect):
Representation of a rectangle as (x, y, w, h), indexable
Constructor handles multiple formats, including:
x, y, w, h
[x, y, w, h]
w, h
(x and y default to 0, 0)
Rect
objects can be splat’d where lists are expected as individual arguments (as in drawBot), i.e.rect(*my_rect)
, or can be passed directly to functions expected a list representation of a rectangle.-
FromCenter
def FromCenter(center, w, h=None)
Create a rect given a center point and a width and height (optional, height will default to width if not specified”)
-
FromMnMnMxMx
def FromMnMnMxMx(extents)
Create a rectangle from
xmin, ymin, xmax, ymax
-
divide
def divide(self, amount, edge, forcePixel=False)
Dividing
Derived from the behavior of the classic Cocoa function CGRectDivide, which takes a rectangle and breaks it into two pieces, based on a pixel amount and an edge.
A quick example: assume you have a rectangle,
r
, defined as such:r = Rect(0, 0, 300, 100)
If you want to break that into a left-hand rectangle that’s 100 pixels wide and a right-hand rectangle that’s 200 pixels wide, you could either say:
left, right = r.divide(100, "mnx")
or you could say
right, left = r.divide(200, "mxx")
where
mxx
is the rightmost edge, andmnx
is the leftmost edge.Centering
A special use-case is if you want to break a rectangle into
three
rectangles, based on the center “edge”, you can do something like this:left, center, right = r.divide(200, "mdx")
This will result in three rectangles, always left-to-right, where left is 50px wide, then center is 200px wide, then right is also 50px wide — anything not in the center will be evenly distributed between left and right, or top-and-bottom in the case of a Y edge.
-
grid
def grid(self, columns=2, rows=None)
Construct a grid; if rows is None, rows = columns
-
inset
def inset(self, dx, dy=None)
Creates padding in the amount of dx and dy. Also does expansion with negative values, or both at once
-
interp
def interp(self, v, other)
Interpolate with another rect
-
ipos
def ipos(self, pt, defaults=(0.5, 0.5), clamp=True)
Get scaled 0-1 bounded (optional) value from a point in a rectangle
-
mnmnmxmx
def mnmnmxmx(self)
Return extents of rectangle as list
-
nonzero
def nonzero(self)
is this rect not just all zeros?
-
origin
def origin(self)
(x, y)
as tuple -
point
def point(self, eh, ev=Edge.MinX)
Get a
Point
at a given compass direction, chosen from- C
- W
- NW
- N
- NE
- E
- SE
- S
- SW
-
rect
def rect(self)
x,y,w,h in list
-
round
def round(self)
round the values in the rectangle to the nearest integer
-
square
def square(self)
take a square from the center of this rect
-
subdivide
def subdivide(self, amount, edge)
Like
divide
, but here you specify the number of equal pieces you want (like columns or rows), and then what edge to start at, i.e... code:: python
r = Rect(0, 0, 500, 100) r.subdivide(5, "mxx") => [Rect([400.0, 0, 100.0, 100]), Rect([300.0, 0, 100.0, 100]), Rect([200.0, 0, 100.0, 100]), Rect([100.0, 0, 100.0, 100]), Rect([0, 0, 100.0, 100])]
will get you five 100-px wide rectangles, right-to-left
(N.B. Does not support center edges, as that makes no sense)
-
subdivide_with_leading
def subdivide_with_leading(self, count, leading, edge, forcePixel=True)
Same as
subdivide
, but inserts leading between each subdivision -
subdivide_with_leadings
def subdivide_with_leadings(self, count, leadings, edge, forcePixel=True)
Same as
subdivide_with_leadings
, but inserts leading between each subdivision, indexing the size of the leading from a list of leadings -
subtract
def subtract(self, amount, edge)
The opposite of
take
, this will remove and not return a piece of the given amount from the given edge.Let’s say you have a 100px-wide square and you want to drop 10px from the right-hand side, you would do:
Rect(100, 100).subtract(10, Edge.MaxX)
, which leaves you withRect([0, 0, 90, 100])
-
take
def take(self, amount, edge, forcePixel=False)
Like
divide
, but here it just returns the “first” rect from a divide call, not all the resulting pieces, i.e. you can “take” 200px from the center of a rectangle by doing thisRect(0, 0, 300, 100).take(200, "mdx")
which will result inRect([50, 0, 200, 100])
-
wh
def wh(self)
the width and height as a tuple
-
xy
def xy(self)
equivalent to origin
-
zero
def zero(self)
disregard origin and set it to (0,0)
functions
-
StSt
source: coldtype/text/composer.pydef StSt(text, font, font_size=24, rect=Rect(1080, 1080), strip=False, multiline=False, lead=True, #xa="mdx", **kwargs)
Set a line of text with a single Style object, passed either with it’s constituent parts (i.e. kwargs) or as an actual
Style
object.Examples:
@renderable() def stst_1(r): # here the styling arguments are "flat" return (StSt("COLDTYPE", Font.ColdObvi(), 100, wdth=0) .align(r))
@renderable() def stst_2(r): # here the styling arguments are encapsulated in the Style object return (StSt("COLDTYPE", Style(Font.ColdObvi(), 100, wdth=1)) .align(r))
-
Glyphwise
source: coldtype/text/composer.pydef Glyphwise(st:str , styler:Callable[[GlyphwiseGlyph], Style] , start:int=0 , line:int=0 , multiline=False)
Build text by applying unique style to each glyph.
Style is determined by a
styler
function (usually a lambda) that is given aGlyphwiseGlyph
containing information about the glyph and its position (index, etc.); styler function must return a Style object to be used for stylingExamples:
@renderable() def glyphwise(r): return (Glyphwise("COLDTYPE", lambda x: Style(Font.ColdObvi(), 200, wdth=x.e)) .align(r))