Пример #1
0
class Graf():
    def __init__(self, lines, container, style=None, **kwargs):
        if isinstance(container, Rect):
            self.container = DATPen().rect(container)
        else:
            self.container = container
        if style and isinstance(style, GrafStyle):
            self.style = style
        else:
            self.style = GrafStyle(**kwargs)
        self.lines = lines
    
    def lineRects(self):
        # which came first, the height or the width???
        rects = []
        leadings = []
        box = self.container.getFrame()
        leftover = box
        for l in self.lines:
            box, leftover = leftover.divide(l.height(), "maxy", forcePixel=True)
            if self.style.leading < 0:
                # need to add pixels back to leftover
                leftover.h += abs(self.style.leading)
            else:
                leading, leftover = leftover.divide(self.style.leading, "maxy", forcePixel=True)
                leadings.append(leading)
            rects.append(box)
        return rects
    
    def width(self):
        if self.style.width > 0:
            return self.style.width
        else:
            return max([l.width() for l in self.lines])

    def fit(self, width=None):
        rects = self.lineRects()
        for idx, l in enumerate(self.lines):
            if width:
                fw = width
            else:
                fw = rects[idx].w - self.style.xp
            l.fit(fw)
        return self
    
    def pens(self, align=False):
        rects = self.lineRects()
        pens = DATPenSet()
        for idx, l in enumerate(self.lines):
            r = rects[idx]
            dps = l.pens().translate(r.x, r.y) # r.x
            dps.addFrame(Rect(r.x, r.y, r.w, r.h))
            #if align:
            #    dps.container = Rect(0, r.y, r.w, r.h)
            #    dps.align(dps.container, x=self.style.x, y=None)
            pens.append(dps)
        return pens
    
    def fpa(self, rect=None):
        return self.fit().pens().align(rect or self.container.getFrame())
Пример #2
0
    def clip_timeline(self, fi, far, sw=30, sh=50, font_name=None):
        seq = DATPens()

        seq += (DATPen()
            .rect(Rect(0, 0, (self.duration * sw), sh)).f(bw(0.5, 0.35)))

        for tidx, t in enumerate(self.tracks):
            for cgidx, cg in enumerate(t.clip_groups):
                for cidx, c in enumerate(cg.clips):
                    r = Rect(c.start*sw, sh*tidx, (c.duration*sw)-2, sh)
                    current = c.start-25 <= fi <= c.end+25
                    if current:
                        seq.append(DATPens([
                            (DATPen()
                                .rect(r)
                                .f(hsl(cgidx*0.4+tidx*0.2, 0.75).lighter(0.2))),
                            (DATText(c.input_text,
                                Style(font_name, 24, load_font=0, fill=bw(0, 1 if tidx == self.workarea_track else 0.5)),
                                r.inset(3, 8)))]))

        on_cut = fi in self.jumps()

        seq.translate(far.w/2 - fi*sw, 10)

        seq.append(DATPen()
            .rect(far.take(sh*len(self.tracks)+20, "mny").take(6 if on_cut else 2, "mdx"))
            .f(hsl(0.9, 1) if on_cut else hsl(0.8, 0.5)))
        
        return seq
Пример #3
0
 def __init__(self, lines, container, style=None, **kwargs):
     if isinstance(container, Rect):
         self.container = DATPen().rect(container)
     else:
         self.container = container
     if style and isinstance(style, GrafStyle):
         self.style = style
     else:
         self.style = GrafStyle(**kwargs)
     self.lines = lines
Пример #4
0
 def shadow(self, clip=None, radius=10, alpha=0.3, color=Color.from_rgb(0,0,0,1)):
     if clip:
         cp = DATPen(fill=None).rect(clip)
         bp = db.BezierPath()
         cp.replay(bp)
         db.clipPath(bp)
     #elif self.rect:
     #    cp = DATPen(fill=None).rect(self.rect).xor(self.dat)
     #    bp = db.BezierPath()
     #    cp.replay(bp)
     #    db.clipPath(bp)
     db.shadow((0, 0), radius*3, list(color.with_alpha(alpha)))
Пример #5
0
        def contactsheet(r: Rect):
            _pngs = list(sorted(self.output_folder.glob("*.png")))
            if sliced:
                pngs = _pngs[sl]
            else:
                pngs = [p for i, p in enumerate(_pngs) if i in sl]

            dps = DATPens()
            dps += DATPen().rect(r).f(self.bg)
            for idx, g in enumerate(r.grid(columns=gx, rows=gy)):
                if idx < len(pngs):
                    dps += DATPen().rect(g).f(None).img(pngs[idx],
                                                        g,
                                                        pattern=False)
            return dps
Пример #6
0
    def draw(self, scale=0.01, dry=True, cm=False):
        if dry:
            with viewer() as v:
                dp = DATPen().record(self.dat).attr(fill=None, stroke=0)
                v.send(SVGPen.Composite([dp], self.page), self.page)
        else:
            self.dat.scale(scale, center=False)
            self.page = self.page.scale(scale)
            b = self.dat.bounds()
            limits = Rect(0, 0, 11, 8.5)
            if cm:
                limits = limits.scale(2.54)
            if b.x >= 0 and b.y >= 0 and b.w <= limits.w and b.h <= limits.h:
                print("Drawing!")
            else:
                print("Too big!", b)
                return False
            ad = axidraw.AxiDraw()
            ad.interactive()
            ad.options.units = 1 if cm else 0
            ad.options.speed_pendown = 50
            ad.options.speed_penup = 50

            ad.connect()
            ad.penup()
            self.ad = ad
            tp = TransformPen(self, (1, 0, 0, -1, 0, self.page.h))
            self.dat.replay(tp)
            time.sleep(MOVE_DELAY)
            ad.penup()
            ad.moveto(0, 0)
            ad.disconnect()
Пример #7
0
 def run(self, render_pass, renderer_state):
     use_pool = True
     if use_pool:
         pool = AppKit.NSAutoreleasePool.alloc().init()
     try:
         db.newDrawing()
         if renderer_state.previewing:
             ps = renderer_state.preview_scale
             db.size(self.rect.w * ps, self.rect.h * ps)
             db.scale(ps, ps)
             DATPen().rect(self.rect).f(self.bg).db_drawPath()
         else:
             db.size(self.rect.w, self.rect.h)
         render_pass.fn(*render_pass.args)
         result = None
         if renderer_state.previewing:
             previews = (render_pass.output_path.parent / "_previews")
             previews.mkdir(exist_ok=True, parents=True)
             preview_frame = previews / render_pass.output_path.name
             db.saveImage(str(preview_frame))
             result = preview_frame
         else:
             render_pass.output_path.parent.mkdir(exist_ok=True,
                                                  parents=True)
             db.saveImage(str(render_pass.output_path))
             result = render_pass.output_path
         db.endDrawing()
     finally:
         if use_pool:
             del pool
     return result
Пример #8
0
 def _emptyPenWithAttrs(self):
     attrs = dict(fill=self.style.fill)
     if self.style.stroke:
         attrs["stroke"] = dict(color=self.style.stroke,
                                weight=self.style.strokeWidth)
     dp = DATPen(**attrs)
     return dp
Пример #9
0
        def stretcher_slnt(w, xy, angle, i, p):
            if abs(angle) in [90, 270]:
                return p
            x0, y0 = xy
            ra = math.radians(90 + angle)
            xdsc = x0 + (-250 - y0) / math.tan(ra)
            xasc = x0 + (1000 - y0) / math.tan(ra)

            np = (p.flatten(flatten) if flatten else
                  p).nonlinear_transform(lambda x, y: (x if is_left(
                      (xdsc, -250), (xasc, 1000), (x, y)) else x + w, y))
            if debug:
                (np.record(DATPen().line([
                    (xdsc, -250), (xasc, 1000)
                ]).outline()).record(DATPen().moveTo(
                    (x0 + 50 / 2, y0 + 50 / 2)).dots(radius=50)))
            return np
Пример #10
0
        def stretcher_slnt(h, xy, angle, i, p):
            if abs(angle) in [90, 270]:
                return p
            x0, y0 = xy
            ra = math.radians(90 + angle)
            ydsc = y0 + (0 - x0) / math.tan(ra)
            yasc = y0 + (p.getFrame().point("E").x - x0) / math.tan(ra)
            p0 = (0, ydsc)
            p1 = (p.getFrame().point("E").x, yasc)

            np = (p.flatten(flatten) if flatten else p).nonlinear_transform(
                lambda x, y: (x, y if not is_left(p0, p1, (x, y)) else y + h))
            if debug:
                (np.record(DATPen().line([p0, p1
                                          ]).outline()).record(DATPen().moveTo(
                                              (x0 + 50 / 2,
                                               y0 + 50 / 2)).dots(radius=50)))
            return np
Пример #11
0
 def runpost(self, result, render_pass, renderer_state):
     res = super().runpost(result, render_pass, renderer_state)
     if Overlay.Info in renderer_state.overlays:
         t = self.rect.take(50, "mxy")
         frame: Frame = render_pass.args[0]
         wave = DATPen()
         if self.audio and sf:
             wave = (self.wavfile.frame_waveform(
                 frame.i, self.rect.inset(0, 300),
                 20).translate(0, self.rect.h / 2).s(1).sw(5))
         return DATPens([
             wave, res,
             DATPen().rect(t).f(bw(0, 0.75)),
             DATText(f"{frame.i} / {self.duration}",
                     Style("Times", 42, load_font=0, fill=bw(1)),
                     t.inset(10))
         ])
     return res
Пример #12
0
    def remove_blanklines(self, blank=None):
        if not blank and self.blankfill:
            blank = self.blankfill

        for line in self.pens:
            txt = reduce(lambda acc, p: p.data.get("txt", "") + acc, line, "")
            if txt == blank:
                line.pens = [DATPen()]

        return self
Пример #13
0
 def stretcher(h, yp, i, p):
     np = (p.flatten(flatten) if flatten else p).nonlinear_transform(
         lambda x, y: (x, y if y < yp else y + h))
     if align == "mdy":
         np.translate(0, -h / 2)
     elif align == "mxy":
         np.translate(0, -h)
     if debug:
         (np.record(DATPen().line([(0, yp),
                                   (p.getFrame().point("E").x, yp)
                                   ]).outline()))
     return np
Пример #14
0
 def frame_waveform(self, fi, r, inc=1, pen=None):
     wave = pen or DATPen()
     samples = self.samples_for_frame(fi)[::inc]
     ww = r.w / len(samples)
     wh = r.h
     for idx, w in enumerate(samples):
         if idx == 0:
             wave.moveTo((r.x, w[0] * wh))
         else:
             wave.lineTo((idx * ww, w[0] * wh))
     wave.endPath()
     wave.f(None).s(1).sw(2)
     return wave
Пример #15
0
def ease(style, x):
    if style == "linear":
        return x, 0.5
    e = eases.get(style)
    if e:
        return e().ease(x), 0.5
    elif False:
        if style in easer_ufo:
            return curve_pos_and_speed(DATPen().glyph(easer_ufo[style]), x)
        else:
            raise Exception("No easing function with that mnemonic")
    else:
        raise Exception("No easing function with that mnemonic")
Пример #16
0
    def scalePenToStyle(self, glyph, in_pen):
        s = self.scale()
        t = Transform()
        try:
            bs = self.style.baselineShift[idx]
        except:
            bs = self.style.baselineShift

        if callable(bs):
            t = t.translate(0, bs(idx))
        else:
            try:
                t = t.translate(0, bs[idx])
            except:
                try:
                    t = t.translate(0, bs)
                except:
                    pass
        t = t.scale(s)
        t = t.translate(glyph.frame.x / self.scale(),
                        glyph.frame.y / self.scale())
        #t = t.translate(0, bs)
        out_pen = DATPen()
        tp = TransformPen(out_pen, (t[0], t[1], t[2], t[3], t[4], t[5]))
        in_pen.replay(tp)
        if self.style.rotate:
            out_pen.rotate(self.style.rotate)

        # TODO this shouldn't be necessary
        if True:
            valid_values = []
            for (move, pts) in out_pen.value:
                if move != "addComponent":
                    valid_values.append((move, pts))
            out_pen.value = valid_values

        return out_pen
Пример #17
0
def ease(style, x) -> [float, float]:
    """
    Though available as a general-purpose function, this logic is usually accessed through something like the `.progress` function on an animation or timeable.

    Return two values — the first is the easing result at a given time x; the second is the tangent to that, if calculable (is not, atm, calculable for the mnemonics given)

    for reference, easing mnemonics:

    * cei = CubicEaseIn
    * ceo = CubicEaseOut
    * ceio = CubicEaseInOut
    * qei = QuadEaseIn
    * qeo = QuadEaseOut
    * qeio = QuadEaseInOut
    * eei = ExponentialEaseIn
    * eeo = ExponentialEaseOut
    * eeio = ExponentialEaseInOut
    * sei = SineEaseIn
    * seo = SineEaseOut
    * seio = SineEaseInOut
    * bei = BounceEaseIn
    * beo = BounceEaseOut
    * beio = BounceEaseInOut
    * eleo = ElasticEaseOut
    * elei = ElasticEaseIn,
    * elieo = ElasticEaseInOut
    """
    if style == "linear":
        return x, 0.5
    e = eases.get(style)
    if e:
        return e().ease(x), 0.5
    elif False:
        if style in easer_ufo:
            return curve_pos_and_speed(DATPen().glyph(easer_ufo[style]), x)
        else:
            raise Exception("No easing function with that mnemonic")
    else:
        raise Exception("No easing function with that mnemonic")
Пример #18
0
 def stretcher(w, xp, i, p):
     np = (p.flatten(flatten) if flatten else p).nonlinear_transform(
         lambda x, y: (x if x < xp else x + w, y))
     if debug:
         (np.record(DATPen().line([(xp, -250), (xp, 1000)]).outline()))
     return np