Exemple #1
0
def getVariableFont(fontOrPath,
                    location,
                    install=True,
                    styleName=None,
                    normalize=True):
    u"""The variablesFontPath refers to the file of the source variable font.
    The nLocation is dictionary axis locations of the instance with values between (0, 1000), e.g.
    dict(wght=0, wdth=1000) or values between  (0, 1), e.g. dict(wght=0.2, wdth=0.6).
    Set normalize to False if the values in location already are matching the axis min/max of the font.
    If there is a [opsz] Optical Size value defined, then store that information in the font.info.opticalSize.
    The optional *styleName* overwrites the *font.info.styleName* of the *ttFont* or the automatic
    location name."""
    if isinstance(fontOrPath, basestring):
        varFont = Font(fontOrPath, name=path2FontName(fontOrPath))
    else:
        varFont = fontOrPath
    fontName, path = generateInstance(varFont.path,
                                      location,
                                      targetDirectory=getInstancePath(),
                                      normalize=normalize)
    # Answer the generated Variable Font instance. Add [opsz] value if is defined in the location, otherwise None.
    return Font(path,
                name=fontName,
                install=install,
                opticalSize=location.get('opsz'),
                location=location,
                styleName=styleName)
Exemple #2
0
 def __repr__(self):
     """
     >>> from pagebot.fonttoolbox.fontpaths import getTestFontsPath
     >>> path = getTestFontsPath() + '/google/roboto/Roboto-Black.ttf'
     >>> font = getFont(path)
     >>> str(font)
     '<Font Roboto-Black>'
     """
     return '<Font %s>' % (path2FontName(self.path) or self.name or 'Untitled').strip()
Exemple #3
0
 def __repr__(self):
     """
     >>> from pagebot.fonttoolbox.fontpaths import getTestFontsPath
     >>> path = getTestFontsPath() + '/google/roboto/Roboto-Black.ttf' # We know this exists in the PageBot repository
     >>> font = getFont(path)
     >>> str(font)
     '<Font Roboto-Black>'
     """
     return '<Font %s>' % (path2FontName(self.path) or self.name
                           or 'Untitled')
Exemple #4
0
    def weightMatch(self, weight):
        """Answers level of matching for the (abbreviated) weight name or number
        with font, in a value between 0 and 1. Currently there is only
        no-match (0) and full-match (1). Future implementations may give a
        float indicator for the level of matching, so the caller can decide on
        the level of threshold.

        >>> from pagebot.fonttoolbox.fontpaths import getTestFontsPath
        >>> path = getTestFontsPath() + '/google/roboto/Roboto-Black.ttf' # We know this exists in the PageBot repository
        >>> font = getFont(path)
        >>> font.info.weightClass
        900
        >>> font.weightMatch(0) # Bad match
        0
        >>> font.weightMatch(800) # Bad match
        0
        >>> font.weightMatch(900) # Exact match
        0
        >>> font.weightMatch(0) # Bad match -
        0
        >>> font.weightMatch('Black') # Black --> Exact match on 900
        1.0
        >>> font.weightMatch('Light') # Light --> No match on 900
        0
        >>> path = getTestFontsPath() + '/google/roboto/Roboto-Regular.ttf' # We know this exists in the PageBot repository
        >>> font = getFont(path)
        >>> font.info.weightClass
        400
        """
        """
        TODO: Fix these tests

        >>> font.weightMatch(400) # Match
        1.0
        >>> font.weightMatch('Regular') # Match
        1.0
        >>> font.weightMatch('Condensed') # Matching with width name has no match.
        0
        """
        if isinstance(weight, (float, int)):  # Comparing by numbers
            # Compare the weight as number as max difference to what we already have.
            w = self.info.weightClass
            if w in FONT_WEIGHT_MATCHES.get(weight, []):
                return 1.0  # Exact match
        else:  # Comparing by string
            fileName = path2FontName(self.path)
            for w in FONT_WEIGHT_MATCHES.get(weight, []):
                if not isinstance(w,
                                  (float, int)) and (w in fileName or w
                                                     in self.info.styleName):
                    return 1.0  # Exacly match
        return 0  # No match
def _recursivelyCollectFontPaths(path, collectedFontPaths):
    u"""Recursive helper function for getFontPaths. If the fileName already exists in the fontPaths, then ignore."""
    if os.path.exists(path):
        if os.path.isdir(path):
            for fileName in os.listdir(path):
                dirPath = path + '/' + fileName
                _recursivelyCollectFontPaths(dirPath, collectedFontPaths)
        else:
            fontName = path2FontName(path) # File name without extension used as key, works for Flat and DrawBot.
            # If fontName is None, it does not have the right extension.
            # Note that files with the same file name will be overwritten, we expect them to be unique in the OS.
            if fontName is not None:
                collectedFontPaths[fontName] = path
Exemple #6
0
def getWeightNames(family):
    # Collect all weight names in increasing order.
    weightClasses = family.getWeights()
    weightNames = ''
    index = 0
    for weightClass, fonts in sorted(weightClasses.items()):
        weightName = '[%d] ' % weightClass
        for font in fonts:
            if index > 24:
                return weightNames
            weightName += ' ' + path2FontName(font.path)
            index += 1
        weightNames += ' ' + weightName
    return weightNames
Exemple #7
0
    def widthMatch(self, width):
        """Answers level of matching for the (abbreviated) width name or number
        with font. Currently there is only no-match (0) and full-match (1).
        Future implementations may give a float indicator for the level of
        matching, so the caller can decide on the level of threshold.

        >>> from pagebot.fonttoolbox.fontpaths import getTestFontsPath
        >>> path = getTestFontsPath() + '/google/roboto/Roboto-Black.ttf' # We know this exists in the PageBot repository
        >>> font = getFont(path)
        >>> font.info.widthClass
        5
        >>> font.widthMatch(0) # Bad match
        0
        >>> font.widthMatch(4) # Close match fails
        0
        >>> font.widthMatch(5) # Exact match
        1.0
        >>> font.widthMatch(6) # Close match fails
        0
        >>> font.widthMatch(10) # Bad match
        0
        >>> path = getTestFontsPath() + '/google/roboto/Roboto-Bold.ttf' # We know this exists in the PageBot repository
        >>> font = Font(path)
        >>> font.info.widthClass
        5
        >>> font.widthMatch(5) # Wrong exact match --> 1000 due to wrong font.info.widthClass
        1.0
        >>> font.widthMatch('Wide') # No match on "Wide"
        0
        >>> #font.widthMatch('Cond') # Exact match on "Cond"
        1.0
        """
        if isinstance(width, (float, int)):
            # Compare the width as number as max difference to what we already have.
            w = self.info.widthClass
            if w <= 100:  # Normalize to 1000
                w *= 100
            if w in FONT_WIDTH_MATCHES.get(width, []):
                return 1.0
        else:  # Comparing by string
            fileName = path2FontName(self.path)
            for w in FONT_WIDTH_MATCHES.get(width, []):
                if not isinstance(w,
                                  (float, int)) and (w in fileName or w
                                                     in self.info.styleName):
                    return 1.0
        return 0
Exemple #8
0
    def match(self, name=None, weight=None, width=None, italic=None):
        """Answers a value between 0 and 1 to the amount that self matches the
        defined parameters. Only defined values count in the matching.

        >>> from pagebot.fonttoolbox.fontpaths import getTestFontsPath
        >>> path = getTestFontsPath() + '/google/roboto/Roboto-Black.ttf'
        >>> font = getFont(path)
        >>> font.info.widthClass, font.info.weightClass
        (5, 900)
        >>> font.match(name='Roboto')
        1.0
        >>> font.match(name='Robo', weight='Black')
        1.0
        >>> # Only match on the name.
        >>> font.match(name='Robo', weight='Light')
        0.5
        >>> font.match(name='Robo', width=5)
        1.0
        """

        """
        TODO: Fix these tests

        >>> font.match(name='Robo', weight=900, width=5)
        1.0
        >>> font.match(name='Robo', weight=900, width=5, italic=True)
        0.75
        >>> font.match(name='Robo', weight='Black', width=5, italic=False)
        1.0
        >>> font.match(name='Robo', weight='Blackish', width=5, italic=False)
        0.75
        """
        matches = []
        fontName = path2FontName(self.path)
        if name is not None:
            matches.append(self.nameMatch(name))
        # Currently the matches only answer 0 or 1. In future implementations this value may vary
        # as float between 0 and 1.
        if weight is not None:
            matches.append(self.weightMatch(weight))
        if width is not None:
            matches.append(self.widthMatch(width))
        if italic is not None:
            matches.append(italic == self.isItalic())
        if not matches:
            return 0  # Avoif division by zero
        return sum(matches)/len(matches) # Normalize to value between 0..1
Exemple #9
0
    def nameMatch(self, pattern):
        u"""Answer level of matching between pattern and the font file name or font.info.fullName.
        Pattern can be a single string or a list of string.

        >>> from pagebot.fonttoolbox.fontpaths import getTestFontsPath
        >>> path = getTestFontsPath() + '/google/roboto/Roboto-Black.ttf' # We know this exists in the PageBot repository
        >>> font = getFont(path)
        >>> font.nameMatch('Black')
        1.0
        >>> font.nameMatch('Blackish')
        0
        >>> font.nameMatch(('Roboto', 'Black'))
        1.0
        """
        fontName = path2FontName(self.path)
        if not isinstance(pattern, (list, tuple)):
            pattern = [pattern]
        for part in pattern:
            if not (part in fontName or part in self.info.fullName):
                return 0
        return 1.0
Exemple #10
0
    def isItalic(self):
        """Answers if this font should be considered to be italic. Currently
        there is only no-match (0) and full-match (1). Future implementations
        may give a float indicator for the level of matching, so the calling
        function can decide on the level of threshold.

        >>> from pagebot.fonttoolbox.fontpaths import getTestFontsPath
        >>> fontPath = getTestFontsPath()
        >>> path = getTestFontsPath() + '/google/roboto/Roboto-BlackItalic.ttf'
        >>> font = getFont(path)
        >>> font.isItalic()
        1
        >>> path = getTestFontsPath() + '/google/roboto/Roboto-Bold.ttf'
        >>> font = Font(path)
        >>> font.isItalic()
        0
        """
        if self.info.italicAngle:
            return 1
        for altName in FONT_ITALIC_MATCHES:
            if altName in path2FontName(self.path) or altName in self.info.styleName:
                return 1.0
        return 0
def buildSpecimenPages(doc, family, pn):
    for font in family.getFonts():
        page = doc[pn]
        page.padding = PADDING
        page.gridX = GRID_X
        pageTitle = path2FontName(font.path)
        # Add filling rectangle for background color of the old paper book.
        # Set z-azis != 0, to make floating elements not get stuck at the background
        newRect(z=-10, w=W, h=H, parent=page, fill=PAPER_COLOR)
        # During development, draw the template scan as background
        # Set z-azis != 0, to make floating elements not get stuck at the background
        if SHOW_TEMPLATE:
            newImage(ATF_PATH, x=0, y=0, z=-10, w=W, parent=page)
        
        # Centered title: family name and style name of the current font.
        titleBs = context.newString(pageTitle, 
                                    style=dict(font=font.path, xTextAlign=CENTER, textFill=0))
        titleBox = newTextBox(titleBs, parent=page, h=2*L,  
                   conditions=[Top2Top(), Fit2Width()],
                   fill=DEBUG_COLOR0)
        titleBox.solve()
        
        largeSampleBox = newTextBox('', parent=page, w=C1+G/2, 
                   conditions=[Float2Top(), Left2Left(), Fit2Bottom()],
                   fill=DEBUG_COLOR1)
        largeSampleBox.solve()

        # In order to fit different words in the fixed space, they will vary in size.
        # But as the variation in sizes is larger than the variation in size, we'll calculate the strings
        # first for the various word lengths and then sort them by size.
        largeSampleSizes = {}
        for n in (4, 5, 6, 7, 7, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10):
            word = getCapitalizedWord(n)
            if word is None:
                continue
            if len(largeSampleSizes) > 10:
                break
            sample = context.newString(word+'\n', style=dict(font=font.path, rLeading=1), w=C1, pixelFit=False)
            sampleFontSize = int(round(sample.fontSize))
            if not sampleFontSize in largeSampleSizes:
                largeSampleSizes[sampleFontSize] = sample                
        print sorted(largeSampleSizes.keys())
           
        largeSample = context.newString('')
        for sampleFontSize, sample in sorted(largeSampleSizes.items(), reverse=True):
            label = context.newString('%d Points\n' % round(sampleFontSize), style=labelStyle)
            #if largeSample.h + sample.h > largeSampleBox.h:
            #    break
            largeSample += label + sample  
            
        largeSampleBox.setText(largeSample)        
        for fontSize, numChars in ((12, 8), (10, 13), (8, 16)):        
            smallSamples = context.newString(getCapWord(numChars), style=dict(font=font.path), w=C2)
            label = context.newString('%d Points\n' % round(smallSamples.fontSize), style=labelStyle)
            shortWordsSample = context.newString(getShortWordText(), 
                        style=dict(font=font.path, fontSize=smallSamples.fontSize, rLeading=1))
            newTextBox(label + smallSamples + ' ' + shortWordsSample, parent=page, w=C2+G/2, h=80, ml=G/2, mb=L,
                       conditions=[Right2Right(), Float2Top(), Float2Left()],
                       fill=DEBUG_COLOR1)
                       
            label = context.newString('%d Points\n' % fontSize, style=labelStyle)
            smallSamples = context.newString(blurb.getBlurb('article', noTags=True), 
                                             style=dict(font=font.path, fontSize=fontSize))
            newTextBox(label + smallSamples, parent=page, w=C2-2, h=80, mb=L, ml=G/2,
                       conditions=[Right2Right(), Float2Top()], 
                       fill=DEBUG_COLOR1)

        glyphSetFrame = newRect(parent=page, mb=L, ml=G/2, padding=L,
                                borders=dict(line=INLINE, stroke=0, strokeWidth=0.5), 
                                conditions=[Right2Right(), Float2Top(), Float2Left(), 
                                            Fit2Right(), Fit2Bottom()], 
                                fill=DEBUG_COLOR2)
        
        glyphSet = context.newString('Subset of characters in Complete Font\n', 
            style=dict(font=font.path, fontSize=8, xTextAlign=CENTER,
            rParagraphTopSpacing=0.25,
            rParagraphBottomSpacing=0.5))
        glyphSet += context.newString(GLYPH_SET, 
            style=dict(font=font.path, fontSize=23, xTextAlign=CENTER, leading=32))
        newTextBox(glyphSet, parent=glyphSetFrame, padding=(1.5*L, L, L, L),
                             borders=dict(line=INLINE, stroke=0, strokeWidth=0.25), 
                             conditions=[Left2Left(), Fit2Right(), Top2Top(), 
                             Fit2Bottom() ], 
                             fill=DEBUG_COLOR3)
        
        pn += 1
    return pn
Exemple #12
0
 def _get_name(self):
     return path2FontName(self.font.path)
Exemple #13
0
def drawFontLabel(p, varFamily, f, fIndex=None, fAxis=None):
    x, y = p
    print(f.info.styleName, f.info.weightClass, f.info.widthClass)

    glyphH = f[GLYPH]
    if not glyphH.width:
        print(glyphH, 'No width')
        return

    s = 0.05 * 1000 / f.info.unitsPerEm
    leading = 2048 / f.info.unitsPerEm
    stroke(None)
    fill(0)
    save()
    translate(x - glyphH.width / 2 * s, y - leading - 50)
    scale(s)
    drawPath(glyphH.path)
    restore()
    y -= leading + 50

    save()
    pathLabel = '-'.join(path2FontName(f.path).split('-')[1:])
    #label = path2FontName(f.path)
    if fAxis is not None:
        label = '@' + fAxis
    elif fIndex is None:
        label = ''
    else:
        label = '#%d ' % fIndex
    label += '%s\n(%s)\n%d' % (pathLabel.replace('.ttf', '').replace(
        '_', '\n').replace('-', '\n'), f.info.styleName, f.info.weightClass)
    bs = context.newString(label, style=dict(fontSize=10, align='center'))
    tw, th = bs.size
    c.text(bs, (x - tw / 2, y - 14))
    restore()
    y -= leading + th - 22

    # Draw marker on actual position of H.stem and H.weight as green dot
    stemValues = f.analyzer.stems.keys()
    if stemValues:  # Cannot find H-stem, skip this marker
        stem = min(stemValues)
        # XOPQ (counter) + H.stem == H.width - H.stem - H.lsb - H.rsb
        width = glyphH.width - stem - glyphH.leftMargin - glyphH.rightMargin

        c.fill((0, 0.5, 0))
        c.stroke(None)
        R = 16
        weightLoc, widthLoc = stem, width / 2
        c.oval(weightLoc - R / 2, widthLoc - R / 2, R, R)
        if fAxis is not None:
            label = '@' + fAxis
        elif fIndex is None:
            label = ''
        else:
            label = '#%d\n' % fIndex
        bs = c.newString(label + ('S:%d\nW:%d\n%d' %
                                  (weightLoc, widthLoc, f.info.weightClass)),
                         style=dict(fontSize=10,
                                    xTextAlign='center',
                                    textFill=blackColor))
        tw, th = bs.size
        c.text(bs, (weightLoc - tw / 2, widthLoc - 24))

        if varFamily.originFont is f:
            # If one of these is the guessed origin font, then draw marker
            c.fill(None)
            c.stroke((0, 0.5, 0), 2)  # Stroke color and width
            R = 23
            c.oval(weightLoc - R / 2, widthLoc - R / 2, R, R)

    else:
        pass
Exemple #14
0
def guessVarFamilyFromPaths(basePath, name=None):
    """Initialize by guessing the self._font axis locations.
    """
    paths = findFontPaths(basePath)
    name = name or path2FontName(basePath)
    return VarFamily(name, paths)