Ejemplo n.º 1
0
def test_calcIntBounds():
    assert calcIntBounds([(0.1, 40.1), (0.1, 100.1), (49.9, 49.9),
                          (78.5, 9.5)]) == (0, 10, 79, 100)

    assert calcIntBounds([(0.1, 40.1), (0.1, 100.1), (49.9, 49.9),
                          (78.5, 9.5)],
                         round=round) == (0, 10, 78, 100)
Ejemplo n.º 2
0
	def recalcBounds(self, glyfTable):
		coords, endPts, flags = self.getCoordinates(glyfTable)
		if len(coords) > 0:
			if 0:
				# This branch calculates exact glyph outline bounds
				# analytically, handling cases without on-curve
				# extremas, etc.  However, the glyf table header
				# simply says that the bounds should be min/max x/y
				# "for coordinate data", so I suppose that means no
				# fancy thing here, just get extremas of all coord
				# points (on and off).  As such, this branch is
				# disabled.

				# Collect on-curve points
				onCurveCoords = [coords[j] for j in range(len(coords))
						 if flags[j] & flagOnCurve]
				# Add implicit on-curve points
				start = 0
				for end in endPts:
					last = end
					for j in range(start, end + 1):
						if not ((flags[j] | flags[last]) & flagOnCurve):
							x = (coords[last][0] + coords[j][0]) / 2
							y = (coords[last][1] + coords[j][1]) / 2
							onCurveCoords.append((x,y))
						last = j
					start = end + 1
				# Add bounds for curves without an explicit extrema
				start = 0
				for end in endPts:
					last = end
					for j in range(start, end + 1):
						if not (flags[j] & flagOnCurve):
							next = j + 1 if j < end else start
							bbox = calcBounds([coords[last], coords[next]])
							if not pointInRect(coords[j], bbox):
								# Ouch!
								warnings.warn("Outline has curve with implicit extrema.")
								# Ouch!  Find analytical curve bounds.
								pthis = coords[j]
								plast = coords[last]
								if not (flags[last] & flagOnCurve):
									plast = ((pthis[0]+plast[0])/2, (pthis[1]+plast[1])/2)
								pnext = coords[next]
								if not (flags[next] & flagOnCurve):
									pnext = ((pthis[0]+pnext[0])/2, (pthis[1]+pnext[1])/2)
								bbox = calcQuadraticBounds(plast, pthis, pnext)
								onCurveCoords.append((bbox[0],bbox[1]))
								onCurveCoords.append((bbox[2],bbox[3]))
						last = j
					start = end + 1

				self.xMin, self.yMin, self.xMax, self.yMax = calcIntBounds(onCurveCoords)
			else:
				self.xMin, self.yMin, self.xMax, self.yMax = calcIntBounds(coords)
		else:
			self.xMin, self.yMin, self.xMax, self.yMax = (0, 0, 0, 0)
Ejemplo n.º 3
0
	def recalcBounds(self, glyfTable):
		coords, endPts, flags = self.getCoordinates(glyfTable)
		if len(coords) > 0:
			if 0:
				# This branch calculates exact glyph outline bounds
				# analytically, handling cases without on-curve
				# extremas, etc.  However, the glyf table header
				# simply says that the bounds should be min/max x/y
				# "for coordinate data", so I suppose that means no
				# fancy thing here, just get extremas of all coord
				# points (on and off).  As such, this branch is
				# disabled.

				# Collect on-curve points
				onCurveCoords = [coords[j] for j in range(len(coords))
						 if flags[j] & flagOnCurve]
				# Add implicit on-curve points
				start = 0
				for end in endPts:
					last = end
					for j in range(start, end + 1):
						if not ((flags[j] | flags[last]) & flagOnCurve):
							x = (coords[last][0] + coords[j][0]) / 2
							y = (coords[last][1] + coords[j][1]) / 2
							onCurveCoords.append((x,y))
						last = j
					start = end + 1
				# Add bounds for curves without an explicit extrema
				start = 0
				for end in endPts:
					last = end
					for j in range(start, end + 1):
						if not (flags[j] & flagOnCurve):
							next = j + 1 if j < end else start
							bbox = calcBounds([coords[last], coords[next]])
							if not pointInRect(coords[j], bbox):
								# Ouch!
								warnings.warn("Outline has curve with implicit extrema.")
								# Ouch!  Find analytical curve bounds.
								pthis = coords[j]
								plast = coords[last]
								if not (flags[last] & flagOnCurve):
									plast = ((pthis[0]+plast[0])/2, (pthis[1]+plast[1])/2)
								pnext = coords[next]
								if not (flags[next] & flagOnCurve):
									pnext = ((pthis[0]+pnext[0])/2, (pthis[1]+pnext[1])/2)
								bbox = calcQuadraticBounds(plast, pthis, pnext)
								onCurveCoords.append((bbox[0],bbox[1]))
								onCurveCoords.append((bbox[2],bbox[3]))
						last = j
					start = end + 1

				self.xMin, self.yMin, self.xMax, self.yMax = calcIntBounds(onCurveCoords)
			else:
				self.xMin, self.yMin, self.xMax, self.yMax = calcIntBounds(coords)
		else:
			self.xMin, self.yMin, self.xMax, self.yMax = (0, 0, 0, 0)
Ejemplo n.º 4
0
def test_calcIntBounds():
    assert calcIntBounds(
        [(0.1, 40.1), (0.1, 100.1), (49.9, 49.9), (78.5, 9.5)]
    ) == (0, 10, 79, 100)

    assert calcIntBounds(
        [(0.1, 40.1), (0.1, 100.1), (49.9, 49.9), (78.5, 9.5)],
        round=round3
    ) == (0, 10, 78, 100)
Ejemplo n.º 5
0
 def _encodeBBox(self, glyphID, glyph):
     assert glyph.numberOfContours != 0, "empty glyph has no bbox"
     if not glyph.isComposite():
         # for simple glyphs, compare the encoded bounding box info with the calculated
         # values, and if they match omit the bounding box info
         currentBBox = glyph.xMin, glyph.yMin, glyph.xMax, glyph.yMax
         calculatedBBox = calcIntBounds(glyph.coordinates)
         if currentBBox == calculatedBBox:
             return
     self.bboxBitmap[glyphID >> 3] |= 0x80 >> (glyphID & 7)
     self.bboxStream += sstruct.pack(bboxFormat, glyph)
Ejemplo n.º 6
0
	def _encodeBBox(self, glyphID, glyph):
		assert glyph.numberOfContours != 0, "empty glyph has no bbox"
		if not glyph.isComposite():
			# for simple glyphs, compare the encoded bounding box info with the calculated
			# values, and if they match omit the bounding box info
			currentBBox = glyph.xMin, glyph.yMin, glyph.xMax, glyph.yMax
			calculatedBBox = calcIntBounds(glyph.coordinates)
			if currentBBox == calculatedBBox:
				return
		self.bboxBitmap[glyphID >> 3] |= 0x80 >> (glyphID & 7)
		self.bboxStream += sstruct.pack(bboxFormat, glyph)
Ejemplo n.º 7
0
def transformGlyf(font, glyphBBox="", alt255UInt16=False):
    glyf = font["glyf"]
    head = font["head"]

    nContourStream = ""
    nPointsStream = ""
    flagStream = ""
    glyphStream = ""
    compositeStream = ""
    bboxStream = ""
    instructionStream = ""
    bboxBitmap = []
    bboxBitmapStream = ""

    for i in range(4 * ((len(glyf.keys()) + 31) / 32)):
        bboxBitmap.append(0)

    for glyphName in glyf.glyphOrder:
        glyph = glyf[glyphName]
        glyphId = glyf.getGlyphID(glyphName)

        alternate255UInt16 = 0

        # nContourStream
        nContourStream += struct.pack(">h", glyph.numberOfContours)

        haveInstructions = False

        if glyph.numberOfContours == 0:
            if glyphBBox == "empty":
                bboxBitmap[glyphId >> 3] |= 0x80 >> (glyphId & 7)
                bboxStream += struct.pack(">hhhh", 0, 0, 0, 0)
            continue
        elif glyph.isComposite():
            # compositeStream
            more = True
            for i in range(len(glyph.components)):
                if i == len(glyph.components) - 1:
                    haveInstructions = hasattr(glyph, "program")
                    more = False
                compositeStream += glyph.components[i].compile(more, haveInstructions, glyf)
        else:
            # nPointsStream
            lastPointIndex = 0
            for i in range(glyph.numberOfContours):
                nPoints = glyph.endPtsOfContours[i] - lastPointIndex + (i == 0)
                data = pack255UInt16(nPoints, alternate=alternate255UInt16)
                if nPoints == 506 and alt255UInt16:
                    num = [ord(v) for v in data]
                    if alternate255UInt16 == 0:
                        assert num == [254, 0]
                    elif alternate255UInt16 == 1:
                        assert num == [253, 1, 250]
                    else:
                        assert num == [255, 253]
                    alternate255UInt16 += 1
                nPointsStream += data
                lastPointIndex = glyph.endPtsOfContours[i]

            # flagStream & glyphStream
            lastX = 0
            lastY = 0
            lastPointIndex = 0
            for i in range(glyph.numberOfContours):
                for j in range(lastPointIndex, glyph.endPtsOfContours[i] + 1):
                    x, y = glyph.coordinates[j]
                    onCurve = glyph.flags[j] & 0x01
                    dx = x - lastX
                    dy = y - lastY
                    lastX = x
                    lastY = y
                    flags, data = packTriplet(dx, dy, onCurve)
                    flagStream += flags
                    glyphStream += data
                lastPointIndex = glyph.endPtsOfContours[i] + 1
            haveInstructions = True

        if haveInstructions:
            instructions = glyph.program.getBytecode()
            # instructionLength
            glyphStream += pack255UInt16(len(instructions), alternate=alt255UInt16)

            # instructionStream
            instructionStream += instructions

        writeBBox = False
        if glyph.isComposite():
            writeBBox = glyphBBox != "nocomposite"
        else:
            coords = glyph.getCoordinates(glyf)[0]
            oldBounds = (glyph.xMin, glyph.yMin, glyph.xMax, glyph.yMax)
            newBounds = calcIntBounds(coords)
            writeBBox = oldBounds != newBounds

        if writeBBox:
            # bboxBitmap
            bboxBitmap[glyphId >> 3] |= 0x80 >> (glyphId & 7)

            # bboxStream
            bboxStream += struct.pack(">hhhh", glyph.xMin, glyph.yMin, glyph.xMax, glyph.yMax)

    bboxBitmapStream = "".join([struct.pack(">B", v) for v in bboxBitmap])

    header = deepcopy(woffTransformedGlyfHeader)
    header["numGlyphs"] = len(glyf.keys())
    header["indexFormat"] = head.indexToLocFormat
    header["nContourStreamSize"] = len(nContourStream)
    header["nPointsStreamSize"] = len(nPointsStream)
    header["flagStreamSize"] = len(flagStream)
    header["glyphStreamSize"] = len(glyphStream)
    header["compositeStreamSize"] = len(compositeStream)
    header["bboxStreamSize"] = len(bboxStream) + len(bboxBitmapStream)
    header["instructionStreamSize"] = len(instructionStream)

    data = sstruct.pack(woffTransformedGlyfHeaderFormat, header)
    data += nContourStream + nPointsStream + flagStream
    data += glyphStream + compositeStream
    data += bboxBitmapStream + bboxStream
    data += instructionStream

    return data
def test_calcIntBounds():
    assert calcIntBounds(
        [(0.1, 40.1), (0.1, 100.1), (49.9, 49.9), (79.5, 9.5)]
    ) == (0, 10, 80, 100)
Ejemplo n.º 9
0
def transformGlyf(font, glyphBBox="", alt255UInt16=False):
    glyf = font["glyf"]
    head = font["head"]

    nContourStream = ""
    nPointsStream = ""
    flagStream = ""
    glyphStream = ""
    compositeStream = ""
    bboxStream = ""
    instructionStream = ""
    bboxBitmap = []
    bboxBitmapStream = ""

    for i in range(4 * ((len(glyf.keys()) + 31) / 32)):
        bboxBitmap.append(0)

    for glyphName in glyf.glyphOrder:
        glyph = glyf[glyphName]
        glyphId = glyf.getGlyphID(glyphName)

        # nContourStream
        nContourStream += struct.pack(">h", glyph.numberOfContours)

        haveInstructions = False

        if glyph.numberOfContours == 0:
            if glyphBBox == "empty":
                bboxBitmap[glyphId >> 3] |= 0x80 >> (glyphId & 7)
                bboxStream += struct.pack(">hhhh", 0, 0, 0, 0)
            continue
        elif glyph.isComposite():
            # compositeStream
            more = True
            for i in range(len(glyph.components)):
                if i == len(glyph.components) - 1:
                    haveInstructions = hasattr(glyph, "program")
                    more = False
                compositeStream += glyph.components[i].compile(more, haveInstructions, glyf)
        else:
            # nPointsStream
            lastPointIndex = 0
            for i in range(glyph.numberOfContours):
                nPointsStream += pack255UInt16(glyph.endPtsOfContours[i] - lastPointIndex + (i == 0), alternate=alt255UInt16)
                lastPointIndex = glyph.endPtsOfContours[i]

            # flagStream & glyphStream
            lastX = 0
            lastY = 0
            lastPointIndex = 0
            for i in range(glyph.numberOfContours):
                for j in range(lastPointIndex, glyph.endPtsOfContours[i] + 1):
                    x, y = glyph.coordinates[j]
                    onCurve = glyph.flags[j] & 0x01
                    dx = x - lastX
                    dy = y - lastY
                    lastX = x
                    lastY = y
                    flags, data = packTriplet(dx, dy, onCurve)
                    flagStream += flags
                    glyphStream += data
                lastPointIndex = glyph.endPtsOfContours[i] + 1
            haveInstructions = True

        if haveInstructions:
            instructions = glyph.program.getBytecode()
            # instructionLength
            glyphStream += pack255UInt16(len(instructions), alternate=alt255UInt16)

            # instructionStream
            instructionStream += instructions

        writeBBox = False
        if glyph.isComposite():
            writeBBox = glyphBBox != "nocomposite"
        else:
            coords = glyph.getCoordinates(glyf)[0]
            oldBounds = (glyph.xMin, glyph.yMin, glyph.xMax, glyph.yMax)
            newBounds = calcIntBounds(coords)
            writeBBox = oldBounds != newBounds

        if writeBBox:
            # bboxBitmap
            bboxBitmap[glyphId >> 3] |= 0x80 >> (glyphId & 7)

            # bboxStream
            bboxStream += struct.pack(">hhhh", glyph.xMin, glyph.yMin, glyph.xMax, glyph.yMax)

    bboxBitmapStream = "".join([struct.pack(">B", v) for v in bboxBitmap])

    header = deepcopy(woffTransformedGlyfHeader)
    header["numGlyphs"] = len(glyf.keys())
    header["indexFormat"] = head.indexToLocFormat
    header["nContourStreamSize"] = len(nContourStream)
    header["nPointsStreamSize"] = len(nPointsStream)
    header["flagStreamSize"] = len(flagStream)
    header["glyphStreamSize"] = len(glyphStream)
    header["compositeStreamSize"] = len(compositeStream)
    header["bboxStreamSize"] = len(bboxStream) + len(bboxBitmapStream)
    header["instructionStreamSize"] = len(instructionStream)

    data = sstruct.pack(woffTransformedGlyfHeaderFormat, header)
    data += nContourStream + nPointsStream + flagStream
    data += glyphStream + compositeStream
    data += bboxBitmapStream + bboxStream
    data += instructionStream

    return data
Ejemplo n.º 10
0
	def recalcBounds(self, glyfTable):
		coords, endPts, flags = self.getCoordinates(glyfTable)
		self.xMin, self.yMin, self.xMax, self.yMax = calcIntBounds(coords)