Example #1
0
 def test_instructionStack(self):
     expected = [
         "reset None", "newPage 200 200", "save",
         "clipPath moveTo 5.0 5.0 lineTo 15.0 5.0 lineTo 15.0 15.0 lineTo 5.0 15.0 closePath",
         "restore", "image Image Object 10 10 0.5 None",
         "blendMode saturation", "transform 1 0 0 1 10 10",
         "drawPath moveTo 10.0 10.0 lineTo 110.0 10.0 lineTo 110.0 110.0 lineTo 10.0 110.0 closePath",
         "textBox foo bar 72.48291015625 84.0 55.0341796875 26.0 center",
         "frameDuration 10", "saveImage * {'myExtraAgrument': True}"
     ]
     with StdOutCollector() as output:
         import drawBot
         drawBot.newDrawing()
         drawBot.size(200, 200)
         drawBot.save()
         path = drawBot.BezierPath()
         path.rect(5, 5, 10, 10)
         drawBot.clipPath(path)
         drawBot.restore()
         im = drawBot.ImageObject()
         with im:
             drawBot.size(20, 20)
             drawBot.rect(5, 5, 10, 10)
         drawBot.image(im, (10, 10), alpha=.5)
         drawBot.blendMode("saturation")
         drawBot.translate(10, 10)
         drawBot.rect(10, 10, 100, 100)
         drawBot.text("foo bar", (100, 100), align="center")
         drawBot.frameDuration(10)
         drawBot.saveImage("*", myExtraAgrument=True)
         drawBot.endDrawing()
     self.assertEqual(output.lines(), expected)
Example #2
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
 def drawCurrentGlyph(self):
     db.newDrawing()
     db.translate(100, 100)
     db.scale(0.8)
     db.fill(None)
     db.stroke(0.2, 0.3, 1)
     db.rect(0, 0, 1000, 1000)
     db.stroke(None)
     db.translate(
         0, 120
     )  # Baseline at 120 from the bottom of the Ideographic Em Square
     db.fill(0, 1, 0, 0.3)
     db.stroke(0)
     db.lineJoin("round")
     dcSelection = set(self.w.deepComponentList.getSelection())
     aeSelection = set(self.w.atomicElementList.getSelection())
     if self._currentGlyphOutline is not None:
         drawOutline(self._currentGlyphOutline)
     if self._currentGlyphComponents:
         for dcIndex, (dcName, atomicElements) in enumerate(
             self._currentGlyphComponents
         ):
             for aeIndex, (aeName, atomicOutline) in enumerate(atomicElements):
                 if dcIndex in dcSelection:
                     if aeIndex in aeSelection:
                         db.fill(1, 0, 0, 0.3)
                     else:
                         db.fill(0, 0, 1, 0.3)
                 else:
                     db.fill(0, 0.3)
                 drawOutline(atomicOutline)
     db.endDrawing()
Example #4
0
 async def reload(self, trigger):
     try:
         load_drawbot = self.args.drawbot
         if load_drawbot:
             if not db:
                 raise Exception("Cannot run drawbot program without drawBot installed")
             else:
                 db.newDrawing()
         self.program = run_path(str(self.filepath))
         if load_drawbot:
             with tempfile.NamedTemporaryFile(suffix=".svg") as tf:
                 db.saveImage(tf.name)
                 self.preview.clear()
                 self.preview.send(f"<div class='drawbot-render'>{tf.read().decode('utf-8')}</div>", None)
             db.endDrawing()
         for k, v in self.program.items():
             if isinstance(v, coldtype.text.reader.Font):
                 await v.load()
                 if v.path not in self.watchee_paths():
                     self.watchees.append([Watchable.Font, v.path])
                 for ext in v.font.getExternalFiles():
                     if ext not in self.watchee_paths():
                         self.watchees.append([Watchable.Font, ext])
             elif isinstance(v, DefconFont):
                 p = Path(v.path).resolve()
                 if p not in self.watchee_paths():
                     self.watchees.append([Watchable.Font, p])
     except Exception as e:
         self.program = None
         self.show_error()
Example #5
0
def draw():
    for i in range(0, 100):
        drawBot.newDrawing()
        drawBot.newPage(1000, 1000)
        drawBot.radialGradient(
            (randint(1,500), randint(1,500)),                         # startPoint
            (randint(1,800), randint(1,800)),                         # endPoint
            [(randint(0,1), randint(0,1), randint(0,1)), (randint(0,1), randint(0,1), randint(0,1)), (randint(0,1), randint(0,1), randint(0,1))],  # colors
            [randint(0,1), randint(0,1), randint(0,1)],                         # locations
            randint(0,1),                                  # startRadius
            randint(0,800)                                # endRadius
        )
# draw a rectangle
        drawBot.rect(randint(0,100), randint(0,100), randint(0,1000), randint(0,1000))

# draw the path
        drawBot.drawPath()
        drawBot.blendMode("multiply")
# set a color
        drawBot.rect(randint(1,10), randint(1,10), randint(1,100), randint(1,100))

# draw oval x, y, width, height
        drawBot.oval(randint(1,500), randint(1,500), randint(1,500), randint(1,500))
        drawBot.oval(randint(1,500), randint(1,500), randint(1,500), randint(1,500))
        drawBot.cmykFill(randint(0,1), randint(0,1), randint(0,1), randint(0,1))
# draw a rectangle
        drawBot.rect(randint(1,10), randint(1,10), randint(1,1000), randint(1,1000))
# set an other color
        drawBot.cmykFill(randint(0,1), randint(0,1), randint(0,1), randint(0,1))
# overlap a second rectangle
        drawBot.rect(randint(1,500), randint(1,500), randint(1,600), randint(1,600))
        drawBot.saveImage(str(i) + '.png' )
        drawBot.endDrawing()
        print(str(i) + ' done.')
Example #6
0
    def Composite(pens, rect, save_to, scale=2):
        db.newDrawing()
        rect = rect.scale(scale)
        db.newPage(rect.w, rect.h)

        def draw(pen, state, data):
            if state == 0:
                DrawBotPen(pen, rect).draw(scale=scale)
            elif state == -1:
                imgf = pen.data.get("imgf")
                if imgf:
                    im = db.ImageObject()
                    im.lockFocus()
                    db.size(rect.w+300, rect.h+300)
                    db.translate(150, 150)
                    db.scale(scale)
                    pen.data["im"] = im
            elif state == 1:
                imgf = pen.data.get("imgf")
                im = pen.data.get("im")
                if imgf and im:
                    im.unlockFocus()
                    imgf(im)
                    x, y = im.offset()
                    db.translate(-150, -150)
                    db.image(im, (x, y))
        
        if isinstance(pens, DATPen):
            pens = [pens]
        for dps in pens:
            dps.walk(draw)
        
        db.saveImage(str(save_to))
        db.endDrawing()
Example #7
0
 def test(self):
     # get the paths
     testPath = os.path.join(tempTestDataDir, "%s.%s" % (scriptName, ext))
     expectedPath = os.path.join(testDataDir,
                                 "expected_%s.%s" % (scriptName, ext))
     expectedOutputPath = os.path.join(testDataDir,
                                       "expected_%s.txt" % scriptName)
     expectedOutput = readExpectedOutput(expectedOutputPath)
     # get drawBot
     import drawBot
     # start a new drawing
     drawBot.newDrawing()
     # execute the script in place
     # temporarily ignore deprecation warnings (there are some from PyObjC :( )
     with warnings.catch_warnings():
         if ignoreDeprecationWarnings:
             warnings.simplefilter("ignore", DeprecationWarning)
         output = self.executeScriptPath(path)
     self.assertEqual(cleanupTraceback(output),
                      cleanupTraceback(expectedOutput))
     # save the image
     drawBot.saveImage(testPath)
     # tell drawBot drawing is done
     drawBot.endDrawing()
     self.assertForFileExtension(ext, expectedPath, testPath)
Example #8
0
def new_drawing(rect: Rect = Rect(1000, 1000), count=1, save_to=None):
    db.newDrawing()
    for idx in range(0, count):
        with new_page(rect) as r:
            yield idx, r
    if save_to:
        db.saveImage(str(save_to))
    db.endDrawing()
Example #9
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
Example #10
0
 def Composite1(pens, rect, save_to, paginate=False, scale=2):
     db.newDrawing()
     rect = rect.scale(scale)
     if not paginate:
         db.newPage(rect.w, rect.h)
     for pen in DrawBotPen.FindPens(pens):
         if paginate:
             db.newPage(rect.w, rect.h)
         DrawBotPen(pen, rect).draw(scale=scale)
     db.saveImage(str(save_to))
     db.endDrawing()
Example #11
0
def draw(x_lines, y_lines, width, height, out_fn):
    mult = 10

    drawBot.newDrawing()
    drawBot.newPage(width * mult, height * mult)
    drawBot.fill(1, 1, 1)
    drawBot.rect(0, 0, width * mult, height * mult)

    draw_colors(x_lines, y_lines, width, height, mult)
    draw_lines(x_lines, y_lines, mult)

    drawBot.saveImage(out_fn)
    drawBot.endDrawing()
Example #12
0
def createPlaceholder(wdt, hgt, locationOnDisk):
    dB.newDrawing()
    dB.newPage(wdt, hgt)

    dB.fill(.5)
    dB.rect(0, 0, dB.width(), dB.height())

    dB.stroke(1)
    dB.strokeWidth(10)

    dB.line((0, 0), (dB.width(), dB.height()))
    dB.line((0, dB.height()), (dB.width(), 0))
    dB.saveImage(f'{locationOnDisk}')
    dB.endDrawing()
Example #13
0
def releaser(fn, path, frame_class=None):
    db.newDrawing()
    r = fn.rect
    w, h = r.wh()
    for idx in range(0, fn.duration):
        print(f"Saving page {idx}...")
        db.newPage(w, h)
        if frame_class:
            fn.func(frame_class(idx, fn))
        else:
            fn.func(r)
    pdf_path = Path(path)
    pdf_path.parent.mkdir(exist_ok=True)
    db.saveImage(str(pdf_path))
    print("Saved pdf", str(pdf_path))
    db.endDrawing()
 def drawCurrentGlyph(self):
     db.newDrawing()
     db.translate(100, 100)
     db.scale(0.8)
     db.fill(None)
     db.stroke(0.2, 0.3, 1)
     db.rect(0, 0, 1000, 1000)
     db.stroke(None)
     db.translate(
         0, 120
     )  # Baseline at 120 from the bottom of the Ideographic Em Square
     db.fill(0, 0.3)
     db.stroke(0)
     if self._currentGlyphPath is not None:
         db.drawPath(self._currentGlyphPath)
     db.endDrawing()
Example #15
0
 def test_formattedString_issue337_part3(self):
     # Verifying we get the correct line height on an empty string
     expected = [
         'reset None', 'newPage 1000 1000',
         'textBox A 0 -34.0 26.8994140625 104.0 left',
         'textBox B 0 -46.0 25.751953125 104.0 left',
         'textBox C 0 -58.0 26.9189453125 104.0 left',
         'textBox A 10 -34.0 26.8994140625 104.0 left',
         'textBox  10 48.0 20.0 104.0 left',
         'textBox C 10 -58.0 26.9189453125 104.0 left', 'saveImage * {}'
     ]
     with StdOutCollector() as output:
         drawBot.newDrawing()
         fs = drawBot.FormattedString("A\nB\nC\n")
         drawBot.text(fs, (0, 60))
         fs = drawBot.FormattedString("A\n\nC\n")
         drawBot.text(fs, (10, 60))
         drawBot.saveImage("*")
         drawBot.endDrawing()
     self.assertEqual(output.lines(), expected)
Example #16
0
 def test(self):
     # get the paths
     testPath = os.path.join(tempDataDir, "%s.%s" % (scriptName, ext))
     expectedPath = os.path.join(dataDir,
                                 "expected_%s.%s" % (scriptName, ext))
     expectedOutputPath = os.path.join(dataDir,
                                       "expected_%s.txt" % scriptName)
     expectedOutput = readExpectedOutput(expectedOutputPath)
     # get drawBot
     import drawBot
     # start a new drawing
     drawBot.newDrawing()
     # execute the script in place
     output = self.executeScriptPath(path)
     self.assertEqual(cleanupTraceback(output),
                      cleanupTraceback(expectedOutput))
     # save the iamge
     drawBot.saveImage(testPath)
     # tell drawBot drawing is done
     drawBot.endDrawing()
     self.assertForFileExtension(ext, expectedPath, testPath)
Example #17
0
 def test(self):
     # get the paths
     testPath = os.path.join(tempTestDataDir, "%s.%s" % (scriptName, ext))
     expectedPath = os.path.join(testDataDir, "expected_%s.%s" % (scriptName, ext))
     expectedOutputPath = os.path.join(testDataDir, "expected_%s.txt" % scriptName)
     expectedOutput = readExpectedOutput(expectedOutputPath)
     # get drawBot
     import drawBot
     # start a new drawing
     drawBot.newDrawing()
     # execute the script in place
     # temporarily ignore deprecation warnings (there are some from PyObjC :( )
     with warnings.catch_warnings():
         if ignoreDeprecationWarnings:
             warnings.simplefilter("ignore", DeprecationWarning)
         output = self.executeScriptPath(path)
     self.assertEqual(cleanupTraceback(output), cleanupTraceback(expectedOutput))
     # save the image
     drawBot.saveImage(testPath)
     # tell drawBot drawing is done
     drawBot.endDrawing()
     self.assertForFileExtension(ext, expectedPath, testPath)
Example #18
0
 def test_instructionStack(self):
     expected = [
         "reset None",
         "newPage 200 200",
         "save",
         "clipPath moveTo 5.0 5.0 lineTo 15.0 5.0 lineTo 15.0 15.0 lineTo 5.0 15.0 closePath",
         "restore",
         "image Image Object 10 10 0.5 None",
         "blendMode saturation",
         "transform 1 0 0 1 10 10",
         "drawPath moveTo 10.0 10.0 lineTo 110.0 10.0 lineTo 110.0 110.0 lineTo 10.0 110.0 closePath",
         "textBox foo bar 82.48291015625 84.0 35.0341796875 26.0 center",
         "frameDuration 10",
         "saveImage * {'myExtraAgrument': True}"
     ]
     with StdOutCollector() as output:
         import drawBot
         drawBot.newDrawing()
         drawBot.size(200, 200)
         drawBot.save()
         path = drawBot.BezierPath()
         path.rect(5, 5, 10, 10)
         drawBot.clipPath(path)
         drawBot.restore()
         im = drawBot.ImageObject()
         with im:
             drawBot.size(20, 20)
             drawBot.rect(5, 5, 10, 10)
         drawBot.image(im, (10, 10), alpha=.5)
         drawBot.blendMode("saturation")
         drawBot.translate(10, 10)
         drawBot.rect(10, 10, 100, 100)
         drawBot.text("foo bar", (100, 100), align="center")
         drawBot.frameDuration(10)
         drawBot.saveImage("*", myExtraAgrument=True)
         drawBot.endDrawing()
     self.assertEqual(output.lines(), expected)
Example #19
0
    for i in range(len(points) - 1):
        draw_square(points[i], points[i + 1])


def generate_points(size: float) -> tuple:
    points = [(size / 2, size / 2)]
    radios = []
    num1, num2 = 0, 50
    i = 0

    while 0 <= points[i][0] < size or 0 <= points[i][1] < size:
        point = points[i][0] + num2 * COEFS[i % 4][0], points[i][1] + num2 * COEFS[i % 4][1]

        points.append(point)
        radios.append(num2)

        i += 1

        num1, num2 = num2, num1 + num2

    return points


if __name__ == '__main__':
    draw.newDrawing()
    draw.size(RESOLUTION[0], RESOLUTION[1])
    draw_spiral(RESOLUTION[0])
    draw.saveImage("FibonacciSpiral.jpeg")
    draw.endDrawing()
Example #20
0
    vertical_pigs = math.floor(CANVAS[1] / ((height + margin / 2) * scale))
    horizontal_pigs = math.floor(CANVAS[0] / ((width + margin) * scale))
    
#    for k in range(FRAMES):
        # db.newPage(*CANVAS)
        # db.frameDuration(1/FRAMES)
    db.save()
    db.scale(scale)
    y = -height
    for i in range(vertical_pigs + 2):
        x = -width
        for j in range(horizontal_pigs + 2):
            db.save()
            db.translate(x, y)
            pig = sh.getGlyphPath(ufo_path, random.choice(glyphs))
            # db.fill(j / random.randint(10, 15), i / random.randint(20, 30), random.uniform(0.6, 0.8), 1)
            db.fill(j / 15, i / 20, 0.7, 1)
            db.drawPath(pig)
            db.restore()
            x += width + margin
        y += height
    db.restore()

    db.fill(1)

    db.font('Cooper Std Black', 150)
    db.text('2019', (60, 200))

    db.saveImage('~/Downloads/pig.gif', imageResolution=300)
    db.endDrawing()
    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)
            hslDonut(rings,
                     ringThickness,
                     holeRadius,
                     fixedValue=eachDisc / (discs - 1),
                     isLuminosityConst=True,
                     captions=False)
        translate(0, 16)
    restore()

    saveImage('cd-roms.pdf')
    endDrawing()

    # Spacing
    txt += "\n" * 2

    for glyphName in txt.listFontGlyphNames():
        txt.appendGlyph("n", "n", glyphName, "n", "n", "space")
        txt.appendGlyph("e", "e", glyphName, "e", "e", "space")



    while txt:
        drawBot.newPage("A4Landscape")
        txt = drawBot.textBox(txt, (40, 40, drawBot.width()-80, drawBot.height()-100))
    
        # Add the date and name of the font
        psName = drawBot.font(fontURL)
        drawBot.font("Arial")
        drawBot.fontSize(11)
        drawBot.text(psName, (40, 40))
    
        date = datetime.today().strftime("%d/%m/%Y")
    
        drawBot.text(date,(drawBot.width()-40,40), align="right")

drawBot.saveImage("specimen.pdf")

drawBot.endDrawing()

 
    d.stroke(1, 0, 0, 0.5)
    d.strokeWidth(annoThickness / sf)
    d.drawPath(path)


totalPages = 0
for g in f.glyphs:
    totalPages += sum([1 for l in g.layers if l.annotations])

for g in f.glyphs:
    for l in g.layers:
        if l.annotations:
            sf, ma, md = new(l,
                             totalPages)  # draw new page and get scalefactor
            texts = []
            for a in l.annotations:
                if a.type == TEXT:
                    texts += [a]
                elif a.type == ARROW:
                    drawArrow(sf, a)
                elif a.type == CIRCLE:
                    drawCircle(sf, a)
                elif a.type in (PLUS, MINUS):
                    drawPlusMinus(sf, a)
            drawText(sf, ma, md, texts)

filePath = "~/Desktop/%s Per-Glyph Comments.pdf" % f.familyName
d.saveImage([filePath])
d.endDrawing()
subprocess.call(["open", "-R", os.path.expanduser(filePath)
                 ])  # show the tagged text in the Finder
Example #24
0
    def _drawReport(self, referenceFont, someFonts, glyphNames, reportPath,
                    caption):
        assert isinstance(reportPath, str) or isinstance(
            reportPath, unicode), 'this should be a string or unicode'
        assert isinstance(someFonts, list), 'this should be a list of RFont'

        prog = ProgressWindow(text='{}: drawing glyphs...'.format(caption),
                              tickCount=len(glyphNames))

        try:
            db.newDrawing()

            twoLinesFontStyles = [
                ff.info.styleName.replace(' ', '\n') for ff in someFonts
            ]
            quota = self._initPage(twoLinesFontStyles)
            for indexName, eachGlyphName in enumerate(glyphNames):
                db.save()
                db.translate(PDF_MARGIN, quota)

                # set name
                for eachSetName, eachGroup in SMART_SETS:
                    if eachGlyphName in eachGroup:
                        setName = eachSetName[3:].replace('.txt', '').replace(
                            '_', ' ')
                        break
                else:
                    setName = ''
                db.text(setName, (COLS['set name'], 0))

                # line number
                db.fill(*BLACK)
                db.text('{:0>4d}'.format(indexName), (COLS['line'], 0))

                # unicode hex
                if eachGlyphName in referenceFont and referenceFont[
                        eachGlyphName].unicode:
                    uniIntValue = referenceFont[eachGlyphName].unicode
                elif eachGlyphName in someFonts[0] and someFonts[0][
                        eachGlyphName].unicode:
                    uniIntValue = someFonts[0][eachGlyphName].unicode
                else:
                    uniIntValue = None

                if uniIntValue:
                    uniHexValue = 'U+{:04X}'.format(uniIntValue)
                    db.fill(*BLACK)
                    db.text(uniHexValue, (COLS['unicode'], 0))

                # os char
                if uniIntValue:
                    txt = db.FormattedString()
                    txt.fontSize(BODY_SIZE_GLYPH)
                    txt.fill(*GRAY)
                    txt += 'H'
                    txt.fill(*BLACK)
                    txt += unichr(uniIntValue)
                    txt.fill(*GRAY)
                    txt += 'p'
                    db.text(txt, (COLS['char'], 0))

                # glyphname
                db.fontSize(BODY_SIZE_TEXT)
                db.text(eachGlyphName, (COLS['glyph name'], 0))

                # glyphs
                db.translate(COLS['template'], 0)
                for eachFont in [referenceFont] + someFonts:
                    if eachGlyphName in eachFont:
                        eachGlyph = eachFont[eachGlyphName]
                        lftRefGL = eachFont['H']
                        rgtRefGL = eachFont['p']

                        db.save()
                        db.scale(BODY_SIZE_GLYPH / eachFont.info.unitsPerEm)
                        db.fill(*GRAY)
                        db.drawGlyph(lftRefGL)
                        db.translate(lftRefGL.width, 0)
                        db.fill(*BLACK)
                        db.drawGlyph(eachGlyph)
                        db.translate(eachGlyph.width, 0)
                        db.fill(*GRAY)
                        db.drawGlyph(rgtRefGL)
                        db.restore()
                    db.translate(TAB_WIDTH, 0)
                db.restore()
                prog.update()

                quota -= TAB_LINE_HEIGHT
                if quota <= PDF_MARGIN:
                    quota = self._initPage(twoLinesFontStyles)

            prog.setTickCount(value=None)
            prog.update(text='{}: saving PDF...'.format(caption))
            db.saveImage(reportPath)
            db.endDrawing()

        except Exception as error:
            prog.close()
            raise error

        prog.close()