Пример #1
0
def fitVariableWidth(varFont, s, w, fontSize, condensedLocation, wideLocation, fixedSize=True, 
        tracking=None, rTracking=None):
    u"""Answer the font instance that makes string s width on the given width *w* for the given *fontSize*.
    The *condensedLocation* dictionary defines the most condensed font instance (optionally including the opsz)
    and the *wideLocation* dictionary defines the most wide font instance (optionally including the opsz).
    The string width for s is calculated with both locations and then the [wdth] value is interpolated and iterated
    until the location is found where the string *s* fits width *w). Note that interpolation may not be enough,
    as the width axis may contain non-linear masters.
    If the requested w outside of what is possible with two locations, then interations are performed to 
    change the size. Again this cannot be done by simple interpolation, as the [opsz] also changes the width.
    It one of the axes does not exist in the font, then use the default setting of the font.
    """
    # TODO: Adjusting by size change (if reequested width is not possible with the width limits of the fon)t)
    # TODO: is not yet implemented.

    # Get the instances for the extreme width locations. This allows the caller to define the actual range
    # of the [wdth] axis to be user, instead of the default minValue and maxValue. E.g. for a range of widths
    # in a headline, the typographer may only want a small change before the line is wrapping, instead 
    # using the full spectrum to extreme condensed.
    condensedFont = getVariableFont(varFont, condensedLocation)
    wideFont = getVariableFont(varFont, wideLocation)
    # Calculate the widths of the string using these two instances.
    condensedFs = newFS(s, style=dict(font=condensedFont.installedName, fontSize=fontSize, tracking=tracking, 
        rTracking=rTracking, textFill=0))
    wideFs = newFS(s, style=dict(font=wideFont.installedName, fontSize=fontSize, tracking=tracking, 
        rTracking=rTracking, textFill=0))
    # Calculate the widths of the strings. 
    # TODO: Handle if these lines would wrap on the given width. In that case we may want to set the wrapped
    # first line back to it's uncondensed value, to make the first wrapped line fit the width.
    condensedWidth, _ = textSize(condensedFs)
    wideWidth, _ = textSize(wideFs)

    # Check if the requested with is inside the boundaries of the font width axis
    if w < condensedWidth: # Requested width is smaller than was was possible using the extreme value of [wdth] axis.
        font = condensedFont
        fs = condensedFs
        location = condensedLocation
    elif w > wideWidth:  # Requested width is larger than was was possible using the extreme value of [wdth] axis.      
        font = wideFont
        fs = wideFs
        location = wideLocation
    else: # Inside the selected [wdth] range, now interpolation the fitting location.
        # TODO: Check if the width of the new string is within tolerance of the request width.
        # This may not be the case if the range of the [wdth] is interpolating in a non-linear way.
        # In that case we may need to do a number of iterations.
        widthRange = wideLocation['wdth'] - condensedLocation['wdth'] 
        location = copy.copy(condensedLocation)
        location['wdth'] += widthRange*(w-condensedWidth)/(wideWidth-condensedWidth)
        font = getVariableFont(varFont, location)
        fs = newFS(s, style=dict(font=font.installedName, fontSize=fontSize, tracking=tracking, rTracking=rTracking, textFill=0))
    # Answer the dictionary with calculated data, so the caller can reuse it, without the need to new expensive recalculations.
    return dict(
        condensendFont=condensedFont, condensedFs=condensedFs, condensedWidth=condensedWidth, condensedLocation=condensedLocation,
        wideFont=wideFont, wideFs=wideFs, wideWidth=wideWidth, wideLocation=wideLocation,
        font=font, fs=fs, width=textSize(fs)[0], location=location
    )
Пример #2
0
 def getTextSize(self, fs=None, w=None):
     """Figure out what the width/height of the text self.fs is, with or given width or
     the styled width of this text box. If fs is defined as external attribute, then the
     size of the string is answers, as if it was already inside the text box."""
     if fs is None:
         fs = self.fs
     return textSize(self.fs, width=w or self.w)
Пример #3
0
    def _drawGlyphMarker(self,
                         axisName,
                         mx,
                         my,
                         glyphName,
                         fontSize,
                         location,
                         strokeW=2):
        # Middle circle
        fill(1)
        stroke(0.7)
        strokeWidth(strokeW)
        oval(mx - fontSize / 2 * self.R, my - fontSize / 2 * self.R,
             fontSize * self.R, fontSize * self.R)

        variableFont = getVariableFont(self.font, location)
        # Show axis name below circle marker?
        if self.showAxisNames and axisName is not None:
            fs = newFS(axisName,
                       style=dict(font=variableFont.installedName,
                                  fontSize=fontSize / 4,
                                  textFill=0))
            tw, th = textSize(fs)
            text(fs, (mx - tw / 2, my - fontSize / 2 * self.R - th * 2 / 3))
        glyphPathScale = fontSize / self.font.info.unitsPerEm
        drawGlyphPath(variableFont,
                      glyphName,
                      mx,
                      my - fontSize / 3,
                      s=glyphPathScale,
                      fillColor=0)
Пример #4
0
 def _drawOverflowMarker(self, px, py, view):
     fs = newFS('[+]',
                style=dict(textFill=(1, 0, 0),
                           font='Verdana-Bold',
                           fontSize=8))
     tw, th = textSize(fs)
     if self.originTop:
         pass
     else:
         text(fs, (px + self.w - 3 - tw, py + th / 2))
Пример #5
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')
Пример #6
0
    def draw(self, origin, view):
        u"""Draw the text on position (x, y). Draw background rectangle and/or frame if
        fill and/or stroke are defined."""
        p = pointOffset(self.oPoint, origin)
        p = self._applyScale(p)
        px, py, _ = p = self._applyAlignment(p)  # Ignore z-axis for now.

        # TODO: Add marker if there is overflow text in the textbox.

        self.drawFrame(p, view)  # Draw optional frame or borders.

        if self.drawBefore is not None:  # Call if defined
            self.drawBefore(self, p, view)

        # Draw the text with horizontal and vertical alignment
        tw, th = textSize(self.fs)
        xOffset = yOffset = 0
        if self.css('yTextAlign') == MIDDLE:
            yOffset = (self.h - self.pb - self.pt - th) / 2
        elif self.css('yTextAlign') == BOTTOM:
            yOffset = self.h - self.pb - self.pt - th
        if self.css('xTextAlign') == CENTER:
            xOffset = (self.w - self.pl - self.pr - tw) / 2
        elif self.css('xTextAlign') == RIGHT:
            xOffset = self.w - self.pl - self.pr - tw

        textShadow = self.textShadow
        if textShadow:
            save()
            setShadow(textShadow)

        textBox(self.fs,
                (px + self.pl + xOffset, py + self.pb - yOffset,
                 self.w - self.pl - self.pr, self.h - self.pb - self.pt))

        if textShadow:
            restore()

        # If there are any child elements, draw them over the text.
        self._drawElements(p, view)

        # Draw markers on TextLine and TextRun positions.
        self._drawBaselines(px, py, view)

        if view.showTextOverflowMarker and self.isOverflow():
            self._drawOverflowMarker(px, py, view)

        if self.drawAfter is not None:  # Call if defined
            self.drawAfter(self, p, view)

        self._restoreScale()
        view.drawElementMetaInfo(
            self, origin)  # Depends on css flag 'showElementInfo'
Пример #7
0
 def getOverflow(self, fs=None, w=None, h=None, doc=None):
     """Flow the text into self and put any overflow in self.next.
     If there is no self.next defined, then store the remaining overflow
     text in self.overflow.
     """
     # If another FormattedString is defined, then use that.
     # Otherwise use the existing self.fs
     if fs is None:
         fs = self.fs
     # Since we cannot test the overflow without drawing in DrawBot, we'll
     # create a text column far outside the page boundaries.
     # Unfortunately this increases the PDF export size.
     h = w or self.h
     w = h or self.w
     if h is None and w is not None:
         # Height of the box is undefined, measure it from the defined column width.
         _, h = drawBot.textSize(fs, width=w)
     elif w is None and h is not None:
         # Width of the box is undefined, measure it from the defined column height.
         w, _ = drawBot.textSize(fs, height=h)
     # Height of the box is undefined, measure it from the defined column width.
     return drawBot.textBox(fs, (10000, 0, w, h))
Пример #8
0
    def _drawBaselines(self, px, py, view):
        # Let's see if we can draw over them in exactly the same position.
        if not view.showTextBoxBaselines and not self.showBaselines:
            return

        fontSize = self.css('baseLineMarkerSize')
        indexStyle = dict(font='Verdana', fontSize=8, textFill=(0, 0, 1))
        yStyle = dict(font='Verdana', fontSize=fontSize, textFill=(0, 0, 1))
        leadingStyle = dict(font='Verdana',
                            fontSize=fontSize,
                            textFill=(1, 0, 0))

        if view.showTextBoxY:
            fs = newFS( ` 0 `, style=indexStyle)
            _, th = textSize(fs)
            text(fs, (px + self.w + 3, py + self.h - th / 4))

        stroke(0, 0, 1)
        strokeWidth(0.5)
        prevY = 0
        for textLine in self.textLines:
            y = textLine.y
            # TODO: Why measures not showing?
            line((px, py + y), (px + self.w, py + y))
            if view.showTextBoxIndex:
                fs = newFS( ` textLine.lineIndex `, style=indexStyle)
                tw, th = textSize(fs)  # Calculate right alignment
                text(fs, (px - 3 - tw, py + y - th / 4))
            if view.showTextBoxY:
                fs = newFS('%d' % round(y), style=yStyle)
                _, th = textSize(fs)
                text(fs, (px + self.w + 3, py + y - th / 4))
            if view.showTextBoxLeading:
                leading = round(abs(y - prevY))
                fs = newFS('%d' % leading, style=leadingStyle)
                _, th = textSize(fs)
                text(fs, (px + self.w + 3, py + prevY - leading / 2 - th / 4))
            prevY = y
Пример #9
0
 def drawContent(self, ox, oy, doc, page, parent):
     """We just need to define drawing of the foreground. The rest of behavior
     for the Text element (including drawing on the background) is handled
     by the base Element class.
     """
     # Store any overflow to be processed by the caller.
     # Note that this should never happen, as the context of the text box
     # better can be processed by self.flowText before any drawing is done.
     # It is assumed that self.h is set, otherwise take the height of the
     # text column that fits all text.
     h = self.h
     w = self.w
     if h is None and w is not None:
         # Height of the box is undefined, measure it from the defined column width.
         _, h = drawBot.textSize(self.fs, width=w)
     elif w is None and h is not None:
         # Width of the box is undefined, measure it from the defined column height.
         w, _ = drawBot.textSize(self.fs, height=h)
     # Else if width and height are both defined or undefined, we can used them as is.
     # In case width and height are both defined, it may result in a new overflow
     # FormattedString. Store that in self.overflow.
     self.overflow = drawBot.textBox(self.fs,
                                     (ox, oy, self.w, self.h or page.h))
Пример #10
0
    def makeGlyphSet(self, page, font):
        """Fill the (self.w, self.h) with a number of children TextBoxes,
        positioned in lines and spaced by fixed distance, using the glyph
        width, ignore kerning.
        Some visual options: 
        - For every font in self.fonts, show the glyph set.
        - Glyphset by cmap of the font, or by string or random selection.
        - Glyph can be black or random selection of a set of colors.
        - Layout in a fixed width/height grid, or as wrapping lines.
        - Size of the glyph boxes is fixed (number in width/height that
        fit on the page) or fixed amount that scales to fit.
        """
        pw = page.w - 2 * PAD  # Usable page width
        ph = page.h - 2 * PAD  # Usable page height

        drawBot.font(font)  # Set the font to DrawBot current
        glyphNames = drawBot.listFontGlyphNames(
        )  # so we can get the set of glyph names.

        tracking = glyphStyle[
            'fontSize'] / 4  # Extra fixed space between the glyphs.
        leading = 1.3  # Leading between the lines
        x = y = 0  # Start at top left of the page (our y goes down).
        for glyphName in glyphNames:  # All glyph names in the current font
            fs = Text.FS(
                '', **glyphStyle)  # Make a new FormattedStringin this style
            fs.appendGlyph(glyphName)  # And add the current glyph name to it.
            tw, th = drawBot.textSize(
                fs)  # Measure the size of the FormattedString
            e = Text(fs, x=x + PAD, y=ph - y)  # Text element with single glyph
            page.addElement(e)  # And add it to the page
            x += tw + tracking  # Calculate the horizontal position of the next box
            if x > pw - PAD:  # If it runs over the right padding of the page
                x = 0  # Start on the left of the next line
                y += glyphStyle[
                    'fontSize'] * leading  # New vertical position of the line
            if y > ph - glyphStyle[
                    'fontSize'] * leading:  # If vertical is running over bottom
                page = typeSpecimen.newPage()  # Then create a new page
                self.initializePage(page, font)  # and initialize it.
                x = y = 0  # Reset the position, starting on top-left of the new page.
Пример #11
0
    def drawElementOrigin(self, e, origin):
        px, py, _ = pointOffset(e.oPoint, origin)
        S = self.css('viewInfoOriginMarkerSize', 4)
        if self.showElementOrigin:
            # Draw origin of the element
            setFillColor(
                (0.5, 0.5, 0.5, 0.1)
            )  # Transparant fill, so we can see the marker on dark backgrounds.
            setStrokeColor(0, 0.25)
            oval(px - S, py - S, 2 * S, 2 * S)
            line((px - S, py), (px + S, py))
            line((px, py - S), (px, py + S))

        if self.showElementDimensions:
            fs = newFS(point2S(e.point3D),
                       style=dict(font=self.css('viewInfoFont'),
                                  fontSize=self.css('viewInfoFontSize'),
                                  leading=self.css('viewInfoLeading'),
                                  textFill=0.1))
            w, h = textSize(fs)
            text(fs, (px - w / 2, py + S * 1.5))
Пример #12
0
def introSlide(canvasWidth, canvasHeight, question):
    db.newPage(canvasWidth, canvasHeight)
    backgroundImage(canvasWidth, canvasHeight)
    db.fill(*rgb(94, 174, 235))
    # db.rect(0, 0, canvasWidth, canvasHeight)
    backgroundSquares(canvasWidth, canvasHeight)
    db.frameDuration(2)

    db.fill(1, 1, 1)
    margin_bottom = 0.1 * canvasHeight
    margin_sides = 0.1 * canvasHeight

    text_box_margin = margin_sides * 0.5
    text_box_width = canvasWidth - margin_sides * 2 - text_box_margin * 2
    text_box_height = canvasHeight - margin_sides - margin_bottom - text_box_margin * 2

    current_font_size = 10
    db.font('ArialNarrow-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(question,
                                             'center',
                                             width=text_box_width)
        # print(current_text_height)
        # print(text_box_height)
        if (current_font_size > 150):
            break
        elif (current_text_height > text_box_height):
            current_font_size -= 2
            break

    db.fontSize(current_font_size)

    db.fill(*rgb(255, 252, 61))
    db.textBox(question, (margin_sides + text_box_margin, margin_bottom +
                          text_box_margin, text_box_width, text_box_height),
               'center')
Пример #13
0
 def _get_textSize(self):
     return drawBot.textSize(self.fs)
Пример #14
0
                translate(indexI * cellSize, indexJ * cellSize)

                lineQualities()
                rect(0, 0, cellSize, cellSize)

                typeQualities(14, 14)
                openTypeFeatures(frac=False, tnum=True)
                result = func(jj, ii)

                # decimal
                if result % 1 != 0:
                    resultStr = f'{Fraction(jj, ii)}'
                    openTypeFeatures(frac=True, tnum=False)

                # big values
                elif abs(result) > 99:  # 3 digits at least (and maybe a minus)
                    txtWdt, txtHgt = textSize(f'{int(result)}')
                    bodySize = 15
                    while txtWdt > (cellSize - 4) and bodySize > 0:
                        bodySize -= .25
                        typeQualities(bodySize, bodySize)
                        txtWdt, txtHgt = textSize(f'{int(result)}')
                    resultStr = f'{int(result)}'

                else:
                    resultStr = f'{int(result)}'

                text(resultStr,
                     (cellSize / 2, cellSize / 2 - fontAscender() / 2.5),
                     align='center')
Пример #15
0
 def getTextSize(self, w=None):
     return drawBot.textSize(self.fs, width=w)
Пример #16
0
 def getTextSize(self):
     """Figure out what the width/height of the text self.fs is."""
     return textSize(self.fs)
Пример #17
0
    def _drawElementsNeedingInfo(self):
        for e, origin in self.elementsNeedingInfo.values():
            p = pointOffset(e.oPoint, origin)
            p = e._applyScale(p)
            px, py, _ = e._applyAlignment(p)  # Ignore z-axis for now.
            if self.showElementInfo:
                # Draw box with element info.
                fs = newFS(e.getElementInfoString(),
                           style=dict(font=self.css('viewInfoFont'),
                                      fontSize=self.css('viewInfoFontSize'),
                                      leading=self.css('viewInfoLeading'),
                                      textFill=0.1))
                tw, th = textSize(fs)
                Pd = 4  # Padding in box and shadow offset.
                tpx = px - Pd / 2  # Make info box outdent the element. Keeping shadow on the element top left corner.
                tpy = py + e.h - th - Pd
                # Tiny shadow
                setFillColor((0.3, 0.3, 0.3, 0.5))
                setStrokeColor(None)
                rect(tpx + Pd / 2, tpy, tw + 2 * Pd, th + 1.5 * Pd)
                # Frame
                setFillColor(self.css('viewInfoFill'))
                setStrokeColor(0.3, 0.25)
                rect(tpx, tpy, tw + 2.5 * Pd, th + 1.5 * Pd)
                text(fs, (tpx + Pd, tpy + th))
                e._restoreScale()

            if self.showElementDimensions:
                # TODO: Make separate arrow functio and better positions
                # Draw width and height measures
                setFillColor(None)
                setStrokeColor(0, 0.25)
                S = self.css('viewInfoOriginMarkerSize', 4)
                x1, y1, x2, y2 = px + e.left, py + e.bottom, e.right, e.top

                # Horizontal measure
                line((x1, y1 - 0.5 * S), (x1, y1 - 3.5 * S))
                line((x2, y1 - 0.5 * S), (x2, y1 - 3.5 * S))
                line((x1, y1 - 2 * S), (x2, y1 - 2 * S))
                # Arrow heads
                line((x1, y1 - 2 * S), (x1 + S, y1 - 1.5 * S))
                line((x1, y1 - 2 * S), (x1 + S, y1 - 2.5 * S))
                line((x2, y1 - 2 * S), (x2 - S, y1 - 1.5 * S))
                line((x2, y1 - 2 * S), (x2 - S, y1 - 2.5 * S))

                fs = newFS(asFormatted(x2 - x1),
                           style=dict(font=self.css('viewInfoFont'),
                                      fontSize=self.css('viewInfoFontSize'),
                                      leading=self.css('viewInfoLeading'),
                                      textFill=0.1))
                tw, th = textSize(fs)
                text(fs, ((x2 + x1) / 2 - tw / 2, y1 - 1.5 * S))

                # Vertical measure
                line((x2 + 0.5 * S, y1), (x2 + 3.5 * S, y1))
                line((x2 + 0.5 * S, y2), (x2 + 3.5 * S, y2))
                line((x2 + 2 * S, y1), (x2 + 2 * S, y2))
                # Arrow heads
                line((x2 + 2 * S, y2), (x2 + 2.5 * S, y2 - S))
                line((x2 + 2 * S, y2), (x2 + 1.5 * S, y2 - S))
                line((x2 + 2 * S, y1), (x2 + 2.5 * S, y1 + S))
                line((x2 + 2 * S, y1), (x2 + 1.5 * S, y1 + S))

                fs = newFS(asFormatted(y2 - y1),
                           style=dict(font=self.css('viewInfoFont'),
                                      fontSize=self.css('viewInfoFontSize'),
                                      leading=self.css('viewInfoLeading'),
                                      textFill=0.1))
                tw, th = textSize(fs)
                text(fs, (x2 + 2 * S - tw / 2, (y2 + y1) / 2))
Пример #18
0
 def textSize(self, bs, w=None, h=None):
     return drawBot.textSize(self._asFs(bs), width=w, height=h)
Пример #19
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))
Пример #20
0
def newFS(t,
          e=None,
          style=None,
          w=None,
          h=None,
          fontSize=None,
          styleName=None,
          tagName=None):
    u"""Answer a *FormattedString* instance from valid attributes in *style*. Set all values after testing
    their existence, so they can inherit from previous style formats.
    If target width *w* or height *h* is defined, then *fontSize* is scaled to make the string fit *w* or *h*."""

    hyphenation(css('hyphenation', e,
                    style))  # TODO: Should be text attribute, not global

    fs = FormattedString('')
    sFont = css('font', e, style)
    if sFont is not None:
        fs.font(sFont)
    # Forced fontSize, then this overwrites the style['fontSize'] if it is there.
    # TODO: add calculation of rFontSize (relative float based on root-fontSize) here too.
    sFontSize = fontSize or css(
        'fontSize', e,
        style) or 16  # May be scaled to fit w or h if target is defined.
    sLeading = css('leading', e, style)
    rLeading = css('rLeading', e, style)
    if sLeading or (rLeading and sFontSize):
        lineHeight = (sLeading or 0) + (rLeading or 0) * (sFontSize or 0)
        if lineHeight:
            fs.lineHeight(lineHeight)
    if sFontSize is not None:
        fs.fontSize(
            sFontSize)  # For some reason fontSize must be set after leading.
    sFallbackFont = css('fallbackFont', e, style)
    if sFallbackFont is not None:
        fs.fallbackFont(sFallbackFont)
    sFill = css('textFill', e, style)
    if sFill is not NO_COLOR:  # Test on this flag, None is valid value
        setFillColor(sFill, fs)
    sCmykFill = css('cmykFill', e, style, NO_COLOR)
    if sCmykFill is not NO_COLOR:
        setFillColor(sCmykFill, fs, cmyk=True)
    sStroke = css('textStroke', e, style, NO_COLOR)
    sStrokeWidth = css('textStrokeWidth', e, style)
    if sStroke is not NO_COLOR and strokeWidth is not None:
        setStrokeColor(sStroke, sStrokeWidth, fs)
    sCmykStroke = css('cmykStroke', e, style, NO_COLOR)
    if sCmykStroke is not NO_COLOR:
        setStrokeColor(sCmykStroke, sStrokeWidth, fs, cmyk=True)
    sAlign = css(
        'xTextAlign', e,
        style)  # Warning: xAlign is used for element alignment, not text.
    if sAlign is not None:  # yTextAlign must be solved by parent container element.
        fs.align(sAlign)
    sParagraphTopSpacing = css('paragraphTopSpacing', e, style)
    rParagraphTopSpacing = css('rParagraphTopSpacing', e, style)
    if sParagraphTopSpacing or (rParagraphTopSpacing and sFontSize):
        fs.paragraphTopSpacing((sParagraphTopSpacing or 0) +
                               (rParagraphTopSpacing or 0) * (sFontSize or 0))
    sParagraphBottomSpacing = css('paragraphBottomSpacing', e, style)
    rParagraphBottomSpacing = css('rParagraphBottomSpacing', e, style)
    if sParagraphBottomSpacing or (rParagraphBottomSpacing and sFontSize):
        fs.paragraphBottomSpacing((sParagraphBottomSpacing or 0) +
                                  (rParagraphBottomSpacing or 0) *
                                  (sFontSize or 0))
    sTracking = css('tracking', e, style)
    rTracking = css('rTracking', e, style)
    if sTracking or (rTracking and sFontSize):
        fs.tracking((sTracking or 0) + (rTracking or 0) * (sFontSize or 0))
    sBaselineShift = css('baselineShift', e, style)
    rBaselineShift = css('rBaselineShift', e, style)
    if sBaselineShift or (rBaselineShift and sFontSize):
        fs.baselineShift((sBaselineShift or 0) + (rBaselineShift or 0) *
                         (sFontSize or 0))
    sOpenTypeFeatures = css('openTypeFeatures', e, style)
    if sOpenTypeFeatures is not None:
        fs.openTypeFeatures([], **sOpenTypeFeatures)
    sTabs = css('tabs', e, style)
    if sTabs is not None:
        fs.tabs(*sTabs)
    sFirstLineIndent = css('firstLineIndent', e, style)
    rFirstLineIndent = css('rFirstLineIndent', e, style)
    # TODO: Use this value instead, if current tag is different from previous tag. How to get this info?
    # sFirstParagraphIndent = style.get('firstParagraphIndent')
    # rFirstParagraphIndent = style.get('rFirstParagraphIndent')
    # TODO: Use this value instead, if currently on top of a new string.
    sFirstColumnIndent = css('firstColumnIndent', e, style)
    rFirstColumnIndent = css('rFirstColumnIndent', e, style)
    if sFirstLineIndent or (rFirstLineIndent and sFontSize):
        fs.firstLineIndent((sFirstLineIndent or 0) + (rFirstLineIndent or 0) *
                           (sFontSize or 0))
    sIndent = css('indent', e, style)
    rIndent = css('rIndent', e, style)
    if sIndent is not None or (rIndent is not None and sFontSize is not None):
        fs.indent((sIndent or 0) + (rIndent or 0) * (sFontSize or 0))
    sTailIndent = css('tailIndent', e, style)
    rTailIndent = css('rTaildIndent', e, style)
    if sTailIndent or (rTailIndent and sFontSize):
        fs.tailIndent((sTailIndent or 0) + (rTailIndent or 0) *
                      (sFontSize or 0))
    sLanguage = css('language', e, style)
    if sLanguage is not None:
        fs.language(sLanguage)

    sUpperCase = css('uppercase', e, style)
    sLowercase = css('lowercase', e, style)
    sCapitalized = css('capitalized', e, style)
    if sUpperCase:
        t = t.upper()
    elif sLowercase:
        t = t.lower()
    elif sCapitalized:
        t = t.capitalize()

    newt = fs + t  # Format plain string t onto new formatted fs.
    if w is not None:  # There is a target width defined, calculate again with the fontSize ratio correction.
        tw, _ = textSize(newt)
        fontSize = w / tw * sFontSize
        newt = newFS(t,
                     e,
                     style,
                     fontSize=fontSize,
                     styleName=styleName,
                     tagName=tagName)
    elif h is not None:  # There is a target height defined, calculate again with the fontSize ratio correction.
        _, th = textSize(newt)
        fontSize = h / th * sFontSize
        newt = newFS(t,
                     e,
                     style,
                     fontSize=fontSize,
                     styleName=styleName,
                     tagName=tagName)

    return newt
Пример #21
0
        print(fontname, "Calculated font size:", fontsize)
        target_dir = os.path.join(what, code)
        if not os.path.exists(target_dir):
            os.makedirs(target_dir)
        with open(path, mode="r") as f:
            for sample in f.readlines():
                sample = sample.strip()
                if sample != "":
                    db.newDrawing()
                    db.newPage(w, h)
                    p = db.BezierPath()
                    db.fill(1)
                    db.stroke(None)
                    db.rect(0, 0, w, h)
                    db.fill(0)
                    # produce SVGs with the text converted
                    # to outlines
                    fs = db.FormattedString(sample,
                                            font=fontname,
                                            fontSize=fontsize)
                    p.text(fs, (w / 2, h_offset), align="center")
                    db.drawPath(p)
                    db.saveImage(os.path.join(target_dir, sample + ".svg"))
                    tw, _ = db.textSize(fs)
                    if tw > (w - 2 * margin):
                        print("Text '%s' in typeface %s is too wide." %
                              (sample, code))
# save Javascript code
with open("sequences.js", "w") as jsf:
    jsf.write("\n".join(script))
Пример #22
0
 def textSize(self, bs, w=None, h=None):
     return drawBot.textSize(bs.fs, width=w, height=h)
            pass
    else:
        style_name = " "
    return style_name

for i, word in enumerate(args.words):

    key = lower_file_name(word)
    fontSize = 1000
    font = fonts[i%len(fonts)]
    sub_folder = font.parent.stem
    bez = db.BezierPath()
    db.fontSize(fontSize)
    db.font(font)
    s = db.FormattedString(word, fontSize=fontSize, font=font)
    content_width, content_height = db.textSize(word)
    space = db.textSize(" ")[0]
    bez.text(s, (0, 0))
    yShift = abs(db.fontDescender())+50
    bez.translate(0, yShift)

    bez_left, bez_bottom, bez_right, bez_top = bez.bounds()


    canvas_width = content_width
    canvas_height = db.fontAscender() + abs(db.fontDescender()) + 100


    cutoff_left = abs(bez_left) if bez_left < 0 else 0
    cutoff_right = bez_right - content_width if bez_right > content_width else 0