示例#1
0
    def draw(self, saving=False, saveTo=None, fmt="pdf", layers=[], fill=None):
        savingToFont = isinstance(fmt, defcon.Font)
        if saving:
            db.newDrawing()
            self.saving = True
        else:
            self.saving = False

        db.newPage(*self.animation.dimensions)
        self.page = Rect.page()

        self.bps = {}
        for l in layers:
            self.bps[l] = RichBezier()

        with db.savedState():
            if fill and not saveTo:
                with db.savedState():
                    db.fill(*fill)
                    db.rect(*self.page)
            self.layers = layers
            self.animation.fn(self)
            self.layers = None
        if self.animation.burn:
            box = self.page.take(64,
                                 Edge.MinY).take(120,
                                                 Edge.MaxX).offset(-24, 24)
            db.fontSize(20)
            db.lineHeight(20)
            db.font("Menlo-Bold")
            db.fill(0, 0.8)
            db.rect(*box.inset(-14, -14).offset(0, 2))
            db.fill(1)
            db.textBox("{:07.2f}\n{:04d}\n{:%H:%M:%S}".format(
                self.time, self.i, datetime.datetime.now()),
                       box,
                       align="center")

        for k, bez in self.bps.items():
            with db.savedState():
                db.fill(*bez.fill)
                db.drawPath(bez.bp)

        if saving:
            if savingToFont:
                for k, bez in self.bps.items():
                    g = defcon.Glyph()
                    g.name = "frame_" + str(self.i)
                    g.unicode = self.i + 48  # to get to 0
                    g.width = self.animation.dimensions[0]
                    bez.bp.drawToPen(g.getPen())
                    fmt.insertGlyph(g)
            else:
                db.saveImage(f"{saveTo}/{self.i}.{fmt}")
            db.endDrawing()

        self.saving = False
示例#2
0
def kerningHeatMap(kerning, glyphNames, isFirstVertical):
    corrections = [kerning[pair] for pair in product(glyphNames, repeat=2)]
    corrections.sort()
    minCorrection, maxCorrection = abs(corrections[0]), abs(corrections[-1])
    if minCorrection < maxCorrection:
        reference = maxCorrection
    else:
        reference = minCorrection

    for jj, glyphY in enumerate(glyphNames):

        # vertical captions
        with savedState():
            translate(-CELL_SIZE, jj * CELL_SIZE)
            typeQualities()
            text(f'{glyphY}', (CELL_SIZE * .5, CELL_SIZE * .2), align='center')

        # drawing the row
        for ii, glyphX in enumerate(glyphNames):
            pair = (glyphY, glyphX) if isFirstVertical else (glyphX, glyphY)
            correction = kerning[pair]

            with savedState():
                translate(ii * CELL_SIZE, jj * CELL_SIZE)

                # horizontal captions
                if jj == 0:
                    typeQualities()
                    text(f'{glyphX}', (CELL_SIZE * .5, -CELL_SIZE * .8),
                         align='center')

                # draw the cells
                factor = .5 + .5 * abs(correction) / reference
                if correction == 0:
                    rectClr = BLACK
                    typeClr = WHITE
                elif correction < 0:
                    rectClr = lerpRGB(WHITE, RED, factor)
                    typeClr = WHITE
                else:
                    rectClr = lerpRGB(WHITE, GREEN, factor)
                    typeClr = BLACK
                shapeQualities(rectClr)
                rect(0, 0, CELL_SIZE, CELL_SIZE)

                if correction != 0:
                    corrStr = f'{abs(correction)}'

                    # just a check for body size
                    if textSize(corrStr)[0] > CELL_SIZE:
                        print(f'[WARNING] {pair} text is too big!')

                    typeQualities(clr=typeClr)
                    text(corrStr, (CELL_SIZE * .5, CELL_SIZE * .2),
                         align='center')
示例#3
0
def hslDonut(rings,
             ringThickness,
             holeRadius,
             fixedValue,
             isLuminosityConst,
             captions=True):
    for angle in range(FULL_CIRCLE):
        for eachRing in range(rings):
            ringFactor = eachRing / (rings - 1)
            radius = holeRadius + eachRing * ringThickness

            if isLuminosityConst:
                rgbClr = hls_to_rgb(angle / FULL_CIRCLE, fixedValue,
                                    ringFactor)
            else:
                rgbClr = hls_to_rgb(angle / FULL_CIRCLE, ringFactor,
                                    fixedValue)
            lineQualities(rgbClr, ringThickness)

            newPath()
            arc((0, 0), radius, angle - .5, angle + .5, clockwise=False)
            drawPath()

        with savedState():
            if angle % 10 == 0 and captions:
                captionRadius = radius + ringThickness
                rotate(angle)

                lineQualities(thickness=.5)
                line((captionRadius - 2, 0), (captionRadius + 2, 0))

                typeQualities()
                text(f'{angle}', (radius + ringThickness + 6, 0))
示例#4
0
def feelingSlide(canvasWidth, canvasHeight, polarity):
    db.newPage(canvasWidth, canvasHeight)

    background_fill = polarityBackground(polarity)

    db.fill(*background_fill)
    db.frameDuration(4)
    db.rect(0, 0, canvasWidth, canvasHeight)

    background_images = os.listdir('background_images/')
    background_image_path = 'background_images/' + background_images[(int)(
        len(background_images) * random.random())]
    # https://forum.drawbot.com/topic/180/how-do-i-size-an-image-with-the-imageobject-or-without/4
    srcWidth, srcHeight = db.imageSize(background_image_path)
    dstWidth, dstHeight = canvasWidth - 50, canvasHeight - 50
    factorWidth = dstWidth / srcWidth
    factorHeight = dstHeight / srcHeight
    with db.savedState():
        db.translate(25, 25)
        with db.savedState():
            db.scale(factorWidth, factorHeight)
            db.image(background_image_path, (0, 0))

    dril_feels_text = db.FormattedString()
    dril_feels_text.append("@dril feels",
                           font="Calibri-Bold",
                           fontSize=150,
                           fill=1,
                           align='center',
                           stroke=background_fill,
                           strokeWidth=0.5)
    db.shadow((0, 0), 50, background_fill)
    db.text(dril_feels_text, (canvasWidth / 2, canvasHeight - 300))

    if polarity < -0.1:
        drils_feeling = "angry"
        db.font("LucidaBlackletter", 250)
    elif polarity < 0.25:
        drils_feeling = "neutral"
        db.font("Helvetica", 180)
    else:
        drils_feeling = "happy"
        db.font("Cortado", 250)

    db.fill(1)
    db.shadow((0, 0), 50, background_fill)
    db.text(drils_feeling, (canvasWidth / 2, 250), align='center')
示例#5
0
def drawCell(glyphName, cellWidth, cellHeight, cellLegendSize):

    # Cell outline
    db.fill(None)
    db.stroke(0)
    db.strokeWidth(0.25)
    db.rect(0, 0, cellWidth, cellHeight)

    charArea = cellWidth / 3.5
    fontSize = charArea * 0.7
    charStartingOffset = (cellWidth * 0.5) - (charArea * 1.5)

    # Glyph sample
    for iH, aH in enumerate(angles):
        for iV, aV in enumerate(reversed(angles)):
            locStr = "%s %s" % (aH, aV)

            f = instances[locStr]
            if glyphName in f:
                g = f[glyphName]

                with db.savedState():
                    db.translate(charStartingOffset, charStartingOffset
                                 )  # Center the nine glyphs in the cell
                    db.translate(
                        iH * charArea,
                        iV * charArea)  # Move to the current glyph in the cell
                    db.translate(charArea * 0.5,
                                 0)  # Offset to center glyph in cell
                    db.translate(0, cellLegendSize *
                                 3)  # Leave room for the legend
                    # Draw
                    db.fill(0)
                    db.stroke(None)
                    db.scale(fontSize / 1000)
                    drawGlyph(g)

                # Legend
                db.fill(None)
                db.stroke(0)
                db.strokeWidth(0.25)
                db.lineCap("round")
                db.line((cellLegendSize, cellLegendSize * 3),
                        (cellWidth - cellLegendSize, cellLegendSize * 3))
                unicodeValueStr = ""
                if g.unicode:
                    unicodeValueStr = hex(g.unicode)
                legendText = "%s\n%s" % (g.name, unicodeValueStr)
                fs = db.FormattedString(legendText,
                                        font="Tilt Neon",
                                        fontSize=cellLegendSize,
                                        tracking=1,
                                        lineHeight=cellLegendSize)
                db.text(fs, (cellLegendSize, cellLegendSize * 1.7))
示例#6
0
def backgroundImage(canvasWidth, canvasHeight):
    background_images = os.listdir('background_images/')
    background_image_path = 'background_images/' + background_images[(int)(
        len(background_images) * random.random())]
    # https://forum.drawbot.com/topic/180/how-do-i-size-an-image-with-the-imageobject-or-without/4
    srcWidth, srcHeight = db.imageSize(background_image_path)
    dstWidth, dstHeight = canvasWidth, canvasHeight
    factorWidth = dstWidth / srcWidth
    factorHeight = dstHeight / srcHeight
    with db.savedState():
        db.scale(factorWidth, factorHeight)
        db.image(background_image_path, (0, 0))
示例#7
0
def drawGlyph(g):
    # Get glyph outline
    f = g.font
    pen = CocoaPen(f)
    g.draw(pen)
    bezierPath = pen.path
    # Draw
    with db.savedState():
        db.translate(-g.width * 0.5, 450)  # Center the glyph
        path = db.BezierPath()
        path.setNSBezierPath(bezierPath)
        db.drawPath(path)
示例#8
0
def startNewPage(pageWidth, pageHeight, margin, header):
    db.newPage(pageWidth, pageHeight)
    # Draw the header
    with db.savedState():
        fs = db.FormattedString("%s Glyph Overview\n" % HEADER_STYLENAME,
                                font="Tilt Neon",
                                fontSize=15)
        fs.append("by Andy Clymer\n%s" % HEADER_URL,
                  font="Tilt Neon",
                  fontSize=8)
        db.translate(margin, db.height() - header - margin)
        db.textBox(fs, (0, 0, db.width() - (margin * 2), header))
示例#9
0
def drawFolds(foldWidth, currentPage):
    ticks = 0
    for y in range(0, int(canvasHeight * 1.3), int(foldWidth * 0.6)):
        with db.savedState():
            yCopy = y
            db.rotate(-30, center=(0, yCopy))
            xOffset = -foldWidth
            for x in range(xOffset, int(canvasWidth * 1.3),
                           int(foldWidth * 1.8)):
                yCopy -= foldWidth * 0.03
                db.rotate(math.sqrt((x - xOffset + 1) * 0.1),
                          center=(x, yCopy))
                fold(x, yCopy, foldWidth, currentPage)
                ticks += 1
                if (ticks > 2000):
                    raise Exception('Maximum depth reached')
示例#10
0
    def test_distribute_on_path(self):
        mistral = Font.Cacheable("~/Type/fonts/fonts/_script/MistralD.otf")

        with test_image(self, "test_distribute.png", Rect(1000,
                                                          1000)) as (i, r):
            s = (StyledString("Hello", Style(mistral, 300)).pens().f(
                hsl(0.3, s=1)).align(r).chain(dbdraw))

            with db.savedState():
                db.fill(None)
                db.stroke(0)
                db.strokeWidth(1)
                db.rect(*s.ambit())

            circle = DraftingPen().oval(r.inset(200)).reverse().rotate(0)
            s2 = (s.copy().zero_translate().distribute_on_path(circle).chain(
                dbdraw))

            self.assertEqual(s.f(), s2.f())
示例#11
0
 def image(self, src=None, opacity=1, rect=None, rotate=0, repeating=False, scale=True):
     bounds = self.dat.bounds()
     src = str(src)
     if not rect:
         rect = bounds
     try:
         img_w, img_h = db.imageSize(src)
     except ValueError:
         print("DrawBotPen: No image")
         return
     x = bounds.x
     y = bounds.y
     if repeating:
         x_count = bounds.w / rect.w
         y_count = bounds.h / rect.h
     else:
         x_count = 1
         y_count = 1
     _x = 0
     _y = 0
     while x <= (bounds.w+bounds.x) and _x < x_count:
         _x += 1
         while y <= (bounds.h+bounds.y) and _y < y_count:
             _y += 1
             with db.savedState():
                 r = Rect(x, y, rect.w, rect.h)
                 #db.fill(1, 0, 0.5, 0.05)
                 #db.oval(*r)
                 if scale == True:
                     db.scale(rect.w/img_w, center=r.point("SW"))
                 elif scale:
                     try:
                         db.scale(scale[0], scale[1], center=r.point("SW"))
                     except TypeError:
                         db.scale(scale, center=r.point("SW"))
                 db.rotate(rotate)
                 db.image(src, (r.x, r.y), alpha=opacity)
             y += rect.h
         y = 0
         x += rect.w
示例#12
0
def answerSlide(canvasWidth, canvasHeight, answer, polarity):
    background_fill = polarityBackground(polarity)
    db.newPage(canvasWidth, canvasHeight)
    db.fill(*background_fill)
    db.rect(0, 0, canvasWidth, canvasHeight)
    db.frameDuration(4)
    background_images = os.listdir('background_images/')
    background_image_path = 'background_images/' + background_images[(int)(
        len(background_images) * random.random())]
    # https://forum.drawbot.com/topic/180/how-do-i-size-an-image-with-the-imageobject-or-without/4
    srcWidth, srcHeight = db.imageSize(background_image_path)
    dstWidth, dstHeight = canvasWidth - 50, canvasHeight - 50
    factorWidth = dstWidth / srcWidth
    factorHeight = dstHeight / srcHeight
    with db.savedState():
        db.translate(25, 25)
        with db.savedState():
            db.scale(factorWidth, factorHeight)
            db.image(background_image_path, (0, 0))

    db.fill(*rgba(*background_fill, 0.1))
    box_width = 0.7 * canvasWidth
    box_height = canvasHeight * 0.7
    x_0 = (canvasWidth - box_width) / 2
    y_0 = (canvasHeight - box_height) / 2 - 100

    text_box_margin = 40
    text_box_width = box_width - text_box_margin * 2
    text_box_height = box_height - text_box_margin * 2

    current_font_size = 10
    db.font('Calibri-Bold', current_font_size)

    # this is not efficient. Don't show anyone I made this
    while True:
        db.fontSize(current_font_size)
        current_font_size += 1
        _, current_text_height = db.textSize(answer,
                                             'left',
                                             width=text_box_width)
        if (current_font_size > 150):
            break
        elif (current_text_height > text_box_height):
            current_font_size -= 2
            break

    db.fontSize(current_font_size)
    db.stroke(*background_fill)
    db.strokeWidth(0.5)
    db.fill(*rgb(255, 252, 61))
    db.textBox(answer, (x_0, y_0, box_width, box_height), 'left')

    # dril says
    d_says = db.FormattedString()
    d_says.append("@dril says:",
                  font="Calibri-Bold",
                  fontSize=100,
                  fill=rgb(255, 252, 61),
                  stroke=background_fill,
                  strokeWidth=2)
    # db.shadow((0,0), 50, background_fill)
    db.text(d_says, (x_0, y_0 + box_height + 30))
示例#13
0
 def draw(self, scale=2, style=None):
     with db.savedState():
         db.scale(scale)
         for attrs, attr in self.findStyledAttrs(style):
             self.applyDATAttribute(attrs, attr)
         db.drawPath(self.bp)
示例#14
0
### Variables
discs = 16
rings = 22
ringThickness = 5
holeRadius = 45

### Instructions
if __name__ == '__main__':
    newDrawing()
    newPage(952, 488)

    translate(width() * .27, height() * .25)
    save()
    for eachDisc in range(discs):
        with savedState():
            scale(1, .65)
            hslDonut(rings,
                     ringThickness,
                     holeRadius,
                     fixedValue=eachDisc / (discs - 1),
                     isLuminosityConst=True,
                     captions=False)
        translate(0, 16)
    restore()

    translate(width() * .44, 0)
    save()
    for eachDisc in range(discs):
        with savedState():
            scale(1, .65)
示例#15
0
import drawBot
drawBot.newDrawing()
drawBot.size(200, 200)

testData = [
    ((25, 25, 50, 50), "rotate", (20,), (25, 25)),
    ((125, 25, 50, 50), "skew", (10, 10), (175, 25)),
    ((25, 125, 50, 50), "scale", (1.2, 1.4), (25, 175)),
]

for r, op, args, center in testData:
    drawBot.fill(0)
    bez = drawBot.BezierPath()
    bez.rect(*r)
    drawBot.drawPath(bez)
    with drawBot.savedState():
        drawBot.fill(1, 0, 0, 0.5)
        bez = drawBot.BezierPath()
        bez.rect(*r)
        getattr(bez, op)(*args, center=center)
        drawBot.drawPath(bez)
    def doExport(self, f, savePath):
        # Export an image of the glyphs

        # Collect the glyph names from this font
        glyphNames = []
        glyphChoice = self.w.exportBox.glyphChoice.get()
        if glyphChoice == 0:
            glyphNames = list(f.selection)
        elif glyphChoice == 1:
            if 'public.glyphOrder' in f.lib.keys():
                allNames = f.lib['public.glyphOrder']
            else:
                allNames = list(f.keys())
                allNames.sort()
            # Only keep glyphs that have art
            for gn in allNames:
                g = f[gn]
                if len(g.contours):
                    glyphNames.append(gn)

        # Find the maximum glyph bounds, to figure out the grid spacing
        xMax = 0
        yMax = 0
        for gn in glyphNames:
            g = f[gn]
            bounds = g.bounds
            if bounds:
                thisXMax = bounds[2] - bounds[0]
                thisYMax = bounds[3] - bounds[1]
                if thisXMax > xMax:
                    xMax = thisXMax
                if thisYMax > yMax:
                    yMax = thisYMax
        xMax = int(math.ceil(xMax)) * self.pageScale
        yMax = int(math.ceil(yMax)) * self.pageScale

        # Figure out how many rows of glyphs we'll need, to lay them out in a square grid
        if len(glyphNames) < 1:
            rowCount = 1
        else:
            rowCount = math.ceil(math.sqrt(len(glyphNames)))
        colCount = math.ceil(len(glyphNames) / rowCount)

        # Work out the page dimensions, with glyphs centered up on a grid of xMax and yMax with a buffer to give a little space to work with
        pageWidth = ((colCount + 1) * xMax * self.bufferFactor)
        pageHeight = ((rowCount + 1) * yMax * self.bufferFactor)

        # Start drawing, keeping track of where each glyph was placed
        glyphLocations = []
        db.newDrawing()
        db.newPage(pageWidth, pageHeight)
        gIdx = 0
        for rowNumber in range(rowCount):
            for colNumber in range(colCount):
                if gIdx < len(glyphNames):
                    gridID = "%s-%s" % (colNumber, rowNumber)
                    gName = glyphNames[gIdx]
                    glyph = f[gName]
                    # Find the position to draw the glyph
                    # The glyph will be drawn centered on the center of each grid location
                    locX = ((colNumber * xMax * self.bufferFactor) +
                            xMax * self.bufferFactor)
                    locY = (pageHeight -
                            (rowNumber * yMax * self.bufferFactor) -
                            (yMax * self.bufferFactor))
                    # Adjust the grid location to center the glyph drawing
                    locX += -glyph.width * 0.5 * self.pageScale
                    locY += -yMax * 0.5
                    glyphLocations.append((gName, gridID))
                    # Draw the glyph
                    with db.savedState():
                        db.translate(locX, locY)
                        db.scale(self.pageScale, self.pageScale)
                        pen = CocoaPen(f)
                        glyph.draw(pen)
                        glyphPath = pen.path
                        path = db.BezierPath()
                        path.setNSBezierPath(glyphPath)
                        db.drawPath(path)
                        # Draw the glyph bounding box, for testing
                        if False:
                            db.fill(None)
                            db.stroke(0)
                            db.strokeWidth(10)
                            db.rect(0, 0, xMax, yMax)
                gIdx += 1

        # Prepare a settings document to save, with the number of rows, columns, spacing, scale, and glyph positions
        drawingData = {}
        drawingData["pageScale"] = self.pageScale
        drawingData["bufferFactor"] = self.bufferFactor
        drawingData["pageWidth"] = pageWidth
        drawingData["pageHeight"] = pageHeight
        drawingData["xMax"] = xMax
        drawingData["yMax"] = yMax
        drawingData["rowCount"] = rowCount
        drawingData["colCount"] = colCount
        drawingData["glyphLocations"] = glyphLocations

        # Save
        db.saveImage(savePath)
        plistPath = os.path.splitext(savePath)[0] + ".plist"
        with open(plistPath, "wb") as plistFile:
            dump(drawingData, plistFile)
for background_image in background_images:
    background_image_paths.append('img/tiles-copy/' + background_image)
# print(background_image_paths)

db.newPage(1240, 496)

tileSize = 124
images = [['i' for i in range(4)] for j in range(10)]

srcWidth, srcHeight = db.imageSize(background_image_paths[0])
dstWidth, dstHeight = tileSize, tileSize
factorWidth  = dstWidth  / srcWidth
factorHeight = dstHeight / srcHeight
for x in range(0, 1240, tileSize):
    for y in range(0, 496, tileSize):
        with db.savedState():
            stepX = int(x/tileSize)
            stepY = int(y/tileSize)
            validPath = False
            while not validPath:
                path = random.choice(background_image_paths)
                if(stepX > 0):
                    if(images[stepX-1][stepY] == path):
                        continue
                if(stepY > 0):
                    if(images[stepX][stepY-1] == path):
                        continue
                validPath = True
            db.translate(x, y)
            db.scale(factorWidth, factorHeight)
            db.image(path, (0, 0) )