Beispiel #1
0
 def _get_controlPointBounds(self):
     from fontTools.misc.transform import Transform
     # storage
     glyphRects = {}
     componentReferences = {}
     # scan loaded glyphs
     for glyphName, glyph in self._glyphs.items():
         if glyphName in self._scheduledForDeletion:
             continue
         glyphRect = glyph.controlPointBounds
         if glyphRect:
             glyphRects[glyphName] = glyphRect
     # scan glyphs that have not been loaded
     if self._glyphSet is not None:
         for glyphName, fileName in self._glyphSet.contents.items():
             if glyphName in self._glyphs or glyphName in self._scheduledForDeletion:
                 continue
             glif = self._glyphSet.getGLIF(glyphName)
             points, components = _fetchControlPointBoundsData(glif)
             if points:
                 glyphRects[glyphName] = calcBounds(points)
             for base, transformation in components:
                 xScale, xyScale, yxScale, yScale, xOffset, yOffset = transformation
                 if glyphName not in componentReferences:
                     componentReferences[glyphName] = []
                 componentReferences[glyphName].append((base, xScale, xyScale, yxScale, yScale, xOffset, yOffset))
     # get the transformed component bounding boxes and update the glyphs
     for glyphName, components in componentReferences.items():
         glyphRect = glyphRects.get(glyphName, (None, None, None, None))
         # XXX this doesn't handle nested components
         for base, xScale, xyScale, yxScale, yScale, xOffset, yOffset in components:
             # base glyph doesn't exist
             if base not in glyphRects:
                 continue
             baseRect = glyphRects[base]
             # base glyph has no points
             if None in baseRect:
                 continue
             # transform the base rect
             transform = Transform(xx=xScale, xy=xyScale, yx=yxScale, yy=yScale, dx=xOffset, dy=yOffset)
             xMin, yMin, xMax, yMax = baseRect
             (xMin, yMin), (xMax, yMax) = transform.transformPoints([(xMin, yMin), (xMax, yMax)])
             componentRect = (xMin, yMin, xMax, yMax)
             # update the glyph rect
             if None in glyphRect:
                 glyphRect = componentRect
             else:
                 glyphRect = unionRect(glyphRect, componentRect)
         # store the updated rect
         glyphRects[glyphName] = glyphRect
     # work out the unified rect
     fontRect = None
     for glyphRect in glyphRects.values():
         if fontRect is None:
             fontRect = glyphRect
         elif glyphRect is not None:
             fontRect = unionRect(fontRect, glyphRect)
     # done
     return fontRect
Beispiel #2
0
def unionBounds(bounds1: Optional[BoundingBox],
                bounds2: Optional[BoundingBox]) -> Optional[BoundingBox]:
    if bounds1 is None:
        return bounds2
    if bounds2 is None:
        return bounds1
    return BoundingBox(*unionRect(bounds1, bounds2))
Beispiel #3
0
def unionBounds(bounds1: BoundingBox | None,
                bounds2: BoundingBox | None) -> BoundingBox | None:
    if bounds1 is None:
        return bounds2
    if bounds2 is None:
        return bounds1
    return BoundingBox(*unionRect(bounds1, bounds2))
Beispiel #4
0
 def getSelectionBounds(self):
     selection = self.selection
     bounds = []
     if self.w.contoursCheckBox.get():
         for contour in selection["contours"]:
             b = contour.bounds
             if b is not None:
                 bounds.append(b)
         for bPoint in selection["bPoints"]:
             x = bPoint.anchor.x
             y = bPoint.anchor.y
             bounds.append((x, y, x, y))
     if self.w.componentsCheckBox.get():
         for component in selection["component"]:
             b = component.bounds
             if b is not None:
                 bounds.append(b)
     if self.w.anchorsCheckBox.get():
         for anchor in selection["anchors"]:
             x = anchor.x
             y = anchor.y
             bounds.append((x, y, x, y))
     if not bounds:
         return None
     total = bounds[0]
     for b in bounds[1:]:
         total = unionRect(total, b)
     return total
 def _qCurveToOne(self, bcp, pt):
     bounds = self.bounds
     bounds = updateBounds(bounds, pt)
     if not pointInRect(bcp, bounds):
         bounds = unionRect(
             bounds, calcQuadraticBounds(self._getCurrentPoint(), bcp, pt))
     self.bounds = bounds
Beispiel #6
0
 def compile(self, ttFont):
     if ttFont.recalcBBoxes:
         # For TT-flavored fonts, xMin, yMin, xMax and yMax are set in table__m_a_x_p.recalc().
         if 'CFF ' in ttFont:
             topDict = ttFont['CFF '].cff.topDictIndex[0]
             self.xMin, self.yMin, self.xMax, self.yMax = intRect(
                 topDict.FontBBox)
         elif 'CFF2' in ttFont:
             topDict = ttFont['CFF2'].cff.topDictIndex[0]
             charStrings = topDict.CharStrings
             fontBBox = None
             for charString in charStrings.values():
                 bounds = charString.calcBounds(charStrings)
                 if bounds is not None:
                     if fontBBox is not None:
                         fontBBox = unionRect(fontBBox, bounds)
                     else:
                         fontBBox = bounds
             if fontBBox is not None:
                 self.xMin, self.yMin, self.xMax, self.yMax = intRect(
                     fontBBox)
     if ttFont.recalcTimestamp:
         self.modified = timestampNow()
     data = sstruct.pack(headFormat, self)
     return data
Beispiel #7
0
def getFontBounds(font):
    """
    Get a tuple of (xMin, yMin, xMax, yMax) for all
    glyphs in the given *font*.
    """
    rect = None
    # defcon
    if hasattr(font, "bounds"):
        rect = font.bounds
    # others
    else:
        for glyph in font:
            # robofab
            if hasattr(glyph,"box"):
                bounds = glyph.box
            # others
            else:
                bounds = glyph.bounds
            if rect is None:
                rect = bounds
                continue
            if rect is not None and bounds is not None:
                rect = unionRect(rect, bounds)
    if rect is None:
        rect = (0, 0, 0, 0)
    return rect
Beispiel #8
0
	def _curveToOne(self, bcp1, bcp2, pt):
		bounds = self.bounds
		bounds = updateBounds(bounds, pt)
		if not pointInRect(bcp1, bounds) or not pointInRect(bcp2, bounds):
			bounds = unionRect(bounds, calcCubicBounds(
					self._getCurrentPoint(), bcp1, bcp2, pt))
		self.bounds = bounds
Beispiel #9
0
def getFontBounds(font):
    """
    Get a tuple of (xMin, yMin, xMax, yMax) for all
    glyphs in the given *font*.
    """
    rect = None
    # defcon
    if hasattr(font, "bounds"):
        rect = font.bounds
    # others
    else:
        for glyph in font:
            # robofab
            if hasattr(glyph, "box"):
                bounds = glyph.box
            # others
            else:
                bounds = glyph.bounds
            if rect is None:
                rect = bounds
                continue
            if rect is not None and bounds is not None:
                rect = unionRect(rect, bounds)
    if rect is None:
        rect = (0, 0, 0, 0)
    return rect
Beispiel #10
0
	def _curveToOne(self, bcp1, bcp2, pt):
		bounds = self.bounds
		bounds = updateBounds(bounds, pt)
		if not pointInRect(bcp1, bounds) or not pointInRect(bcp2, bounds):
			bounds = unionRect(bounds, calcCubicBounds(
					self._getCurrentPoint(), bcp1, bcp2, pt))
		self.bounds = bounds
Beispiel #11
0
	def _qCurveToOne(self, bcp, pt):
		bounds = self.bounds
		bounds = updateBounds(bounds, pt)
		if not pointInRect(bcp, bounds):
			bounds = unionRect(bounds, calcQuadraticBounds(
					self._getCurrentPoint(), bcp, pt))
		self.bounds = bounds
Beispiel #12
0
def _bounds(color_glyph: ColorGlyph,
            quantize_factor: int = 1) -> Optional[Tuple[int, int, int, int]]:
    bounds = None
    for root in color_glyph.painted_layers:
        for context in root.breadth_first():
            if not isinstance(context.paint, PaintGlyph):
                continue
            paint_glyph: PaintGlyph = cast(PaintGlyph, context.paint)
            glyph_bbox = _transformed_glyph_bounds(color_glyph.ufo,
                                                   paint_glyph.glyph,
                                                   context.transform)
            if glyph_bbox is None:
                continue
            if bounds is None:
                bounds = glyph_bbox
            else:
                bounds = unionRect(bounds, glyph_bbox)
    if bounds is None:
        return
    # before quantizing to integer values > 1, we must first round floats to
    # int using the same rounding function (i.e. otRound) that fontTools
    # glyf table's compile method will use to round any float coordinates.
    bounds = tuple(otRound(v) for v in bounds)
    if quantize_factor > 1:
        return _quantize_bounding_rect(*bounds, factor=quantize_factor)
    return bounds
Beispiel #13
0
def draw(surface, paths, text, features):
    bounds = None
    lines = []
    y = 0
    for path in paths:
        font = BlackRendererFont(path)

        buf = hb.Buffer()
        buf.add_str(text)
        buf.guess_segment_properties()
        hb.shape(font.hbFont, buf, features)

        line, rect, height = makeLine(buf, font, y)
        lines.append((font, line, rect, y))

        if bounds is None:
            bounds = rect
        bounds = unionRect(bounds, rect)
        y += height

    with surface.canvas(bounds) as canvas:
        for font, line, rect, y in lines:
            with canvas.savedState():
                # Center align the line.
                x = (bounds[2] - rect[2]) / 2
                canvas.translate(x, y)
                for glyph in line:
                    with canvas.savedState():
                        canvas.translate(glyph.xOffset, glyph.yOffset)
                        font.drawGlyph(glyph.name, canvas)
                    canvas.translate(glyph.xAdvance, glyph.yAdvance)
Beispiel #14
0
 def _distributeSpacing(self, index, title):
     glyph = CurrentGlyph()
     if glyph is None:
         return
     rects, selectedContours, selectedBPoints = getSelectionData(glyph)
     if len(rects) < 3:
         return
     widths = []
     heights = []
     edgeRect = None
     for rect in rects:
         xMin, yMin, xMax, yMax = rect
         widths.append(xMax - xMin)
         heights.append(yMax - yMin)
         if edgeRect is None:
             edgeRect = rect
         else:
             edgeRect = unionRect(edgeRect, rect)
     objectWidth = sum(widths)
     objectHeight = sum(heights)
     xMin, yMin, xMax, yMax = edgeRect
     overallWidth = xMax - xMin
     overallHeight = yMax - yMin
     availableXSpace = overallWidth - objectWidth
     availableYSpace = overallHeight - objectHeight
     xSpace = availableXSpace / (len(rects) - 1)
     ySpace = availableYSpace / (len(rects) - 1)
     spaceBetweenObjects = (xSpace, ySpace)[index]
     ordered = [(bPoint.anchor[index], (bPoint.anchor[0], bPoint.anchor[1],
                                        bPoint.anchor[0], bPoint.anchor[1]),
                 bPoint) for bPoint in selectedBPoints]
     ordered += [(contour.bounds[index], contour.bounds, contour)
                 for contour in selectedContours]
     ordered.sort()
     glyph.prepareUndo(title)
     prevEdge = None
     for pos, bounds, obj in ordered[:-1]:
         xMin, yMin, xMax, yMax = bounds
         width = xMax - xMin
         height = yMax - yMin
         size = (width, height)[index]
         if prevEdge is None:
             newPos = (xMin, yMin)[index]
         else:
             newPos = prevEdge + spaceBetweenObjects
         d = newPos - pos
         print(d)
         if d != 0:
             if index == 0:
                 obj.moveBy((d, 0))
             else:
                 obj.moveBy((0, d))
         prevEdge = newPos + size
     for bPoint in selectedBPoints:
         bPoint.round()
     for contour in selectedContours:
         contour.round()
     glyph.changed()
     glyph.performUndo()
     UpdateCurrentGlyphView()
Beispiel #15
0
 def _get_controlPointBounds(self):
     fontRect = None
     for glyph in self:
         glyphRect = glyph.controlPointBounds
         if glyphRect is None:
             continue
         if fontRect is None:
             fontRect = glyphRect
         else:
             fontRect = unionRect(fontRect, glyphRect)
     return fontRect
Beispiel #16
0
 def _get_controlPointBounds(self):
     fontRect = None
     for glyph in self:
         glyphRect = glyph.controlPointBounds
         if glyphRect is None:
             continue
         if fontRect is None:
             fontRect = glyphRect
         else:
             fontRect = unionRect(fontRect, glyphRect)
     return fontRect
def glyphBoundsRepresentationFactory(glyph):
    bounds = None
    for group in (glyph, glyph.components):
        for obj in group:
            b = obj.bounds
            if b is not None:
                if bounds is None:
                    bounds = b
                else:
                    bounds = unionRect(bounds, b)
    return bounds
Beispiel #18
0
 def bounds(self):
     bounds = None
     for path, colorID in self.layers:
         if not path.elementCount():
             continue
         pathBounds = rectFromNSRect(path.controlPointBounds())
         if bounds is None:
             bounds = pathBounds
         else:
             bounds = unionRect(bounds, pathBounds)
     return bounds
Beispiel #19
0
 def _getContourComponentBounds(self, attr):
     bounds = None
     subObjects = [contour for contour in self]
     subObjects += [component for component in self.components]
     for subObject in subObjects:
         b = getattr(subObject, attr)
         if b is not None:
             if bounds is None:
                 bounds = b
             else:
                 bounds = unionRect(bounds, b)
     return bounds
Beispiel #20
0
 def fromSeq(cls, seq: Sequence[Tuple[Rectangle, Any]]):
     if len(seq) == 0:
         # empty tree, pass None for bounds as a special case
         return cls(None, None, None, None)
     elif len(seq) == 1:
         bounds, leaf = seq[0]
         return cls(bounds, leaf, None, None)
     mid = len(seq) // 2
     left = cls.fromSeq(seq[:mid])
     right = cls.fromSeq(seq[mid:])
     bounds = unionRect(left[0], right[0])
     return cls(bounds, None, left, right)
Beispiel #21
0
def glyphBoundsRepresentationFactory(glyph):
    # base glyph
    pen = BoundsPen(glyph.getParent())
    glyph.draw(pen)
    bounds = pen.bounds
    # components
    for component in glyph.components:
        b = component.bounds
        if b is not None:
            if bounds is None:
                bounds = b
            else:
                bounds = unionRect(bounds, b)
    return bounds
Beispiel #22
0
def _bbox(f, gnames, points, scale=1):
    gset = f.glyphSet
    bbox = (0, 0, 0, 0)
    for i, gname in enumerate(gnames):
        if hasattr(points, '__len__') and i == len(points):
            points.append((bbox[2] / scale, 0))
        pt = points[i] if i < len(points) else (0, 0)
        g = gset[gname]._glyph
        if g is None or not hasattr(g, 'xMin'):
            gbox = (0, 0, 0, 0)
        else:
            gbox = (g.xMin * scale, g.yMin * scale, g.xMax * scale,
                    g.yMax * scale)
        bbox = arrayTools.unionRect(
            bbox, arrayTools.offsetRect(gbox, pt[0] * scale, pt[1] * scale))
    return bbox
Beispiel #23
0
    def makeFontBoundingBox(self):
        """
        Make a bounding box for the font.

        **This should not be called externally.** Subclasses
        may override this method to handle the bounds creation
        in a different way if desired.
        """
        if not hasattr(self, "glyphBoundingBoxes"):
            self.glyphBoundingBoxes = self.makeGlyphsBoundingBoxes()
        fontBox = None
        for glyphName, glyphBox in self.glyphBoundingBoxes.items():
            if glyphBox is None:
                continue
            if fontBox is None:
                fontBox = glyphBox
            else:
                fontBox = unionRect(fontBox, glyphBox)
        if fontBox is None:  # unlikely
            fontBox = BoundingBox(0, 0, 0, 0)
        return fontBox
Beispiel #24
0
def unionBounds(bounds1, bounds2):
    if bounds1 is None:
        return bounds2
    if bounds2 is None:
        return bounds1
    return BoundingBox(*unionRect(bounds1, bounds2))
Beispiel #25
0
 def union(self, otherRect):
     return Rect.FromMnMnMxMx(unionRect(self.mnmnmxmx(), otherRect.mnmnmxmx()))
Beispiel #26
0
 def _get_controlPointBounds(self):
     from fontTools.misc.transform import Transform
     # storage
     glyphRects = {}
     componentReferences = {}
     # scan loaded glyphs
     for glyphName, glyph in self._glyphs.items():
         if glyphName in self._scheduledForDeletion:
             continue
         glyphRect = glyph.controlPointBounds
         if glyphRect:
             glyphRects[glyphName] = glyphRect
     # scan glyphs that have not been loaded
     if self._glyphSet is not None:
         for glyphName, fileName in self._glyphSet.contents.items():
             if glyphName in self._glyphs or glyphName in self._scheduledForDeletion:
                 continue
             glif = self._glyphSet.getGLIF(glyphName)
             points, components = _fetchControlPointBoundsData(glif)
             if points:
                 glyphRects[glyphName] = calcBounds(points)
             for base, transformation in components:
                 xScale, xyScale, yxScale, yScale, xOffset, yOffset = transformation
                 if glyphName not in componentReferences:
                     componentReferences[glyphName] = []
                 componentReferences[glyphName].append(
                     (base, xScale, xyScale, yxScale, yScale, xOffset,
                      yOffset))
     # get the transformed component bounding boxes and update the glyphs
     for glyphName, components in componentReferences.items():
         glyphRect = glyphRects.get(glyphName, (None, None, None, None))
         # XXX this doesn't handle nested components
         for base, xScale, xyScale, yxScale, yScale, xOffset, yOffset in components:
             # base glyph doesn't exist
             if base not in glyphRects:
                 continue
             baseRect = glyphRects[base]
             # base glyph has no points
             if None in baseRect:
                 continue
             # transform the base rect
             transform = Transform(xx=xScale,
                                   xy=xyScale,
                                   yx=yxScale,
                                   yy=yScale,
                                   dx=xOffset,
                                   dy=yOffset)
             xMin, yMin, xMax, yMax = baseRect
             (xMin, yMin), (xMax, yMax) = transform.transformPoints([
                 (xMin, yMin), (xMax, yMax)
             ])
             componentRect = (xMin, yMin, xMax, yMax)
             # update the glyph rect
             if None in glyphRect:
                 glyphRect = componentRect
             else:
                 glyphRect = unionRect(glyphRect, componentRect)
         # store the updated rect
         glyphRects[glyphName] = glyphRect
     # work out the unified rect
     fontRect = None
     for glyphRect in glyphRects.values():
         if fontRect is None:
             fontRect = glyphRect
         elif glyphRect is not None:
             fontRect = unionRect(fontRect, glyphRect)
     # done
     return fontRect
Beispiel #27
0
def test_unionRect():
    assert unionRect((0, 10, 20, 30), (0, 40, 20, 50)) == (0, 10, 20, 50)
Beispiel #28
0
def test_unionRect():
    assert unionRect((0, 10, 20, 30), (0, 40, 20, 50)) == (0, 10, 20, 50)