Example #1
0
    def __init__(self, fontname: str) -> None:
        self.face = freetype.Face(fontname)

        height_base = int(BASE_FONT)
        self.face.set_char_size(height=PRESCALE * height_base * 64)

        dim = 1024
        self.margin = 3

        self.packer = SkyLine(dim, dim)

        load_results = loadCached()

        if load_results is not None:
            self.atlas, self.image = load_results
        else:
            self.atlas = {}
            self.image = numpy.zeros((dim, dim), dtype=numpy.uint8)

        old_set = frozenset(list(self.atlas.keys()))

        import string
        chars = string.digits + string.ascii_letters + string.punctuation + ' '

        #self.addGlyphs(string.digits + string.letters + string.punctuation)

        for i in chars:
            self.getGlyph(i)

        new_set = frozenset(list(self.atlas.keys()))
        if old_set != new_set:
            saveCached(self.image, self.atlas)
Example #2
0
    def __init__(self, fontname):
        self.face = freetype.Face(fontname)
        pre = time.time()

        height_base = int(BASE_FONT)
        self.face.set_char_size(height=PRESCALE * height_base * 64)

        dim = 1024
        self.margin = 3

        self.packer = SkyLine(dim, dim)

        load_results = loadCached()

        if load_results is not None:
            self.atlas, self.image = load_results
        else:
            self.atlas = {}
            self.image = numpy.zeros((dim, dim), dtype=numpy.uint8)

        old_set = frozenset(list(self.atlas.keys()))

        import string
        chars = string.digits + string.ascii_letters + string.punctuation + ' '

        #self.addGlyphs(string.digits + string.letters + string.punctuation)

        for i in chars:
            self.getGlyph(i)

        d = time.time() - pre

        new_set = frozenset(list(self.atlas.keys()))
        if old_set != new_set:
            saveCached(self.image, self.atlas)
Example #3
0
class SDFTextAtlas(object):
    def __init__(self, fontname):
        self.face = freetype.Face(fontname)
        pre = time.time()

        height_base = int(BASE_FONT)
        self.face.set_char_size(height=PRESCALE * height_base * 64)

        dim = 1024
        self.margin = 3

        self.packer = SkyLine(dim, dim)

        load_results = loadCached()

        if load_results is not None:
            self.atlas, self.image = load_results
        else:
            self.atlas = {}
            self.image = numpy.zeros((dim, dim), dtype=numpy.uint8)

        old_set = frozenset(list(self.atlas.keys()))

        import string
        chars = string.digits + string.ascii_letters + string.punctuation + ' '

        #self.addGlyphs(string.digits + string.letters + string.punctuation)

        for i in chars:
            self.getGlyph(i)

        d = time.time() - pre

        new_set = frozenset(list(self.atlas.keys()))
        if old_set != new_set:
            saveCached(self.image, self.atlas)


    def addGlyphs(self, multi):
        """
        Add multiple glyphs at a time, packing by best-packing-score first
        Execution time is poor, and gains don't seem to be worth increased execution time
        The packer algorithm could almost certainly made smarter (specifically, the "find" algo)

        :param multi:
        :return:
        """
        # Tuples of (char, ae, bitmap)

        glyphs = []

        # Pre-build the bitmap info
        for char in multi:
            self.face.load_char(char)
            #bitmap = self.face.glyph.bitmap
            #w,h = bitmap.width, bitmap.rows
            #bl, bt = self.face.glyph.metrics.horiBearingX/64.0, self.face.glyph.metrics.horiBearingY/64.0
            #bm = numpy.array(bitmap.buffer, dtype=numpy.ubyte).reshape(h,w)
            #ha = self.face.glyph.metrics.horiAdvance/64.0

            ae = AtlasEntry.fromGlyph(self.face.glyph)
            #bm = numpy.array(self.face.glyph.bitmap.buffer, dtype=numpy.ubyte).reshape(ae.h, ae.w)
            w, h = self.face.glyph.bitmap.width, self.face.glyph.bitmap.rows
            bm = distance_transform_bitmap(self.face.glyph.bitmap, self.margin)

            #print char, bl, bt, self.face.glyph.metrics.horiBearingX/64.0, self.face.glyph.metrics.horiBearingY/64.0, ha/64.0, w
            #glyphs.append((char, w, h, bl, bt, ha, bm))
            glyphs.append((char, ae, bm))

        # Submit a list of rects to pack to the packer
        packlist = [(x[1].w + 2 * self.margin, x[1].h + 2 * self.margin) for x in glyphs]
        multiple = self.packer.pack_multiple(packlist)
        assert len(multiple) == len(packlist)

        # Now fill those rects
        fw = float(self.packer.width)
        fh = float(self.packer.height)

        for (char, ae, bm), (x0, y0) in zip(glyphs, multiple):
            x1, y1 = x0 + ae.w + 2 * self.margin, y0 + ae.h + 2 * self.margin
            ae.updatePos(self.packer.width, self.packer.height, x0, y0, x1, y1)

            self.atlas[char] = ae
            self.image[y0:y1, x0:x1] = bm

    def addGlyph(self, char):
        self.face.load_char(char)

        bitmap = self.face.glyph.bitmap

        w,h = bitmap.width, bitmap.rows


        ae = AtlasEntry.fromGlyph(self.face.glyph)

        pos = self.packer.pack(ae.w + 2 * self.margin, ae.h + 2 * self.margin)
        if pos is not None:

            x0, y0 = pos
            x1, y1 = x0 + ae.w, y0 + ae.h
            x1 += 2 * self.margin
            y1 += 2 * self.margin

            self.image[y0:y1, x0:x1] = distance_transform_bitmap(bitmap, self.margin)


            ae.updatePos(self.packer.width, self.packer.height, x0 , y0, x1, y1)

            self.atlas[char] = ae


    def getGlyph(self, char):
        try:
            return self.atlas[char]
        except KeyError:
            self.addGlyph(char)

        return self.atlas[char]
Example #4
0
class SDFTextAtlas:
    atlas: Dict[str, AtlasEntry]
    image: 'npt.NDArray[numpy.uint8]'

    def __init__(self, fontname: str) -> None:
        self.face = freetype.Face(fontname)

        height_base = int(BASE_FONT)
        self.face.set_char_size(height=PRESCALE * height_base * 64)

        dim = 1024
        self.margin = 3

        self.packer = SkyLine(dim, dim)

        load_results = loadCached()

        if load_results is not None:
            self.atlas, self.image = load_results
        else:
            self.atlas = {}
            self.image = numpy.zeros((dim, dim), dtype=numpy.uint8)

        old_set = frozenset(list(self.atlas.keys()))

        import string
        chars = string.digits + string.ascii_letters + string.punctuation + ' '

        #self.addGlyphs(string.digits + string.letters + string.punctuation)

        for i in chars:
            self.getGlyph(i)

        new_set = frozenset(list(self.atlas.keys()))
        if old_set != new_set:
            saveCached(self.image, self.atlas)


    def addGlyphs(self, multi: str) -> None:
        """
        Add multiple glyphs at a time, packing by best-packing-score first
        Execution time is poor, and gains don't seem to be worth increased execution time
        The packer algorithm could almost certainly made smarter (specifically, the "find" algo)

        :param multi:
        :return:
        """
        # Tuples of (char, ae, bitmap)

        glyphs = []

        # Pre-build the bitmap info
        for char in multi:
            self.face.load_char(char)
            #bitmap = self.face.glyph.bitmap
            #w,h = bitmap.width, bitmap.rows
            #bl, bt = self.face.glyph.metrics.horiBearingX/64.0, self.face.glyph.metrics.horiBearingY/64.0
            #bm = numpy.array(bitmap.buffer, dtype=numpy.ubyte).reshape(h,w)
            #ha = self.face.glyph.metrics.horiAdvance/64.0

            ae = AtlasEntry.fromGlyph(self.face.glyph)
            #bm = numpy.array(self.face.glyph.bitmap.buffer, dtype=numpy.ubyte).reshape(ae.h, ae.w)
            w, h = self.face.glyph.bitmap.width, self.face.glyph.bitmap.rows
            bm = distance_transform_bitmap(self.face.glyph.bitmap, self.margin)

            #print char, bl, bt, self.face.glyph.metrics.horiBearingX/64.0, self.face.glyph.metrics.horiBearingY/64.0, ha/64.0, w
            #glyphs.append((char, w, h, bl, bt, ha, bm))
            glyphs.append((char, ae, bm))

        # Submit a list of rects to pack to the packer
        packlist = [(x[1].w + 2 * self.margin, x[1].h + 2 * self.margin) for x in glyphs]
        multiple = self.packer.pack_multiple(packlist)
        assert len(multiple) == len(packlist)

        for (char, ae, bm), (x0, y0) in zip(glyphs, multiple):
            x1, y1 = x0 + ae.w + 2 * self.margin, y0 + ae.h + 2 * self.margin
            ae.updatePos(self.packer.width, self.packer.height, x0, y0, x1, y1)

            self.atlas[char] = ae
            self.image[y0:y1, x0:x1] = bm

    def addGlyph(self, char: str) -> None:
        self.face.load_char(char)

        bitmap = self.face.glyph.bitmap

        w,h = bitmap.width, bitmap.rows


        ae = AtlasEntry.fromGlyph(self.face.glyph)

        pos = self.packer.pack(ae.w + 2 * self.margin, ae.h + 2 * self.margin)
        if pos is not None:

            x0, y0 = pos
            x1, y1 = x0 + ae.w, y0 + ae.h
            x1 += 2 * self.margin
            y1 += 2 * self.margin

            self.image[y0:y1, x0:x1] = distance_transform_bitmap(bitmap, self.margin)


            ae.updatePos(self.packer.width, self.packer.height, x0 , y0, x1, y1)

            self.atlas[char] = ae


    def getGlyph(self, char: str) -> AtlasEntry:
        v = self.atlas.get(char)
        if v is not None:
            return v

        self.addGlyph(char)

        return self.atlas[char]