Esempio n. 1
0
    def __init__(self, name, size, bold=False, italic=False, dpi=None):
        super(FreeTypeFont, self).__init__()

        if dpi is None:
            dpi = 96  # as of pyglet 1.1; pyglet 1.0 had 72.

        # Check if font name/style matches a font loaded into memory by user
        lname = name and name.lower() or ''
        if (lname, bold, italic) in self._memory_fonts:
            font = self._memory_fonts[lname, bold, italic]
            self._set_face(font.face, size, dpi)
            return

        # Use fontconfig to match the font (or substitute a default).
        ft_library = ft_get_library()

        match = self.get_fontconfig_match(name, size, bold, italic)
        if not match:
            raise base.FontException('Could not match font "%s"' % name)

        f = FT_Face()
        if fontconfig.FcPatternGetFTFace(match, FC_FT_FACE, 0, byref(f)) != 0:
            value = FcValue()
            result = fontconfig.FcPatternGet(match, FC_FILE, 0, byref(value))
            if result != 0:
                raise base.FontException('No filename or FT face for "%s"' % \
                                         name)
            result = FT_New_Face(ft_library, value.u.s, 0, byref(f))
            if result:
                raise base.FontException('Could not load "%s": %d' % \
                                         (name, result))

        fontconfig.FcPatternDestroy(match)

        self._set_face(f, size, dpi)
Esempio n. 2
0
    def render(self, text):
        face = self.font.face
        FT_Set_Char_Size(face, 0, self.font._face_size, self.font._dpi,
                         self.font._dpi)
        glyph_index = fontconfig.FcFreeTypeCharIndex(byref(face), ord(text[0]))
        error = FT_Load_Glyph(face, glyph_index, FT_LOAD_RENDER)
        if error != 0:
            raise base.FontException('Could not load glyph for "%c"' % text[0],
                                     error)
        glyph_slot = face.glyph.contents
        width = glyph_slot.bitmap.width
        height = glyph_slot.bitmap.rows
        baseline = height - glyph_slot.bitmap_top
        lsb = glyph_slot.bitmap_left
        advance = int(f26p6_to_float(glyph_slot.advance.x))
        mode = glyph_slot.bitmap.pixel_mode
        pitch = glyph_slot.bitmap.pitch

        if mode == FT_PIXEL_MODE_MONO:
            # BCF fonts always render to 1 bit mono, regardless of render
            # flags. (freetype 2.3.5)
            bitmap_data = cast(glyph_slot.bitmap.buffer,
                               POINTER(c_ubyte * (pitch * height))).contents
            data = (c_ubyte * (pitch * 8 * height))()
            data_i = 0
            for byte in bitmap_data:
                # Data is MSB; left-most pixel in a byte has value 128.
                data[data_i + 0] = (byte & 0x80) and 255 or 0
                data[data_i + 1] = (byte & 0x40) and 255 or 0
                data[data_i + 2] = (byte & 0x20) and 255 or 0
                data[data_i + 3] = (byte & 0x10) and 255 or 0
                data[data_i + 4] = (byte & 0x08) and 255 or 0
                data[data_i + 5] = (byte & 0x04) and 255 or 0
                data[data_i + 6] = (byte & 0x02) and 255 or 0
                data[data_i + 7] = (byte & 0x01) and 255 or 0
                data_i += 8
            pitch <<= 3
        elif mode == FT_PIXEL_MODE_GRAY:
            # Usual case
            data = glyph_slot.bitmap.buffer
        else:
            raise base.FontException('Unsupported render mode for this glyph')

        # pitch should be negative, but much faster to just swap tex_coords
        img = image.ImageData(width, height, 'A', data, pitch)
        glyph = self.font.create_glyph(img)
        glyph.set_bearings(baseline, lsb, advance)
        t = list(glyph.tex_coords)
        glyph.tex_coords = t[9:12] + t[6:9] + t[3:6] + t[:3]

        return glyph
Esempio n. 3
0
    def _load_font_face_from_system(self):
        match = get_fontconfig().find_font(self.name, self.size, self.bold,
                                           self.italic)
        if not match:
            raise base.FontException('Could not match font "%s"' % self.name)

        font_face = match.face
        if not font_face:
            # Try to load from file directly
            if not match.file:
                raise base.FontException('No filename for "%s"' % self.name)

            font_face = self._load_font_face_from_file(match.file)

        return font_face
Esempio n. 4
0
    def __init__(self, data):
        self.buffer = (ctypes.c_byte * len(data))()
        ctypes.memmove(self.buffer, data, len(data))

        ft_library = ft_get_library()
        self.face = FT_Face()
        r = FT_New_Memory_Face(ft_library, self.buffer, len(self.buffer), 0,
                               self.face)
        if r != 0:
            raise base.FontException('Could not load font data')

        self.name = self.face.contents.family_name
        self.bold = self.face.contents.style_flags & FT_STYLE_FLAG_BOLD != 0
        self.italic = self.face.contents.style_flags & FT_STYLE_FLAG_ITALIC != 0

        # Replace Freetype's generic family name with TTF/OpenType specific
        # name if we can find one; there are some instances where Freetype
        # gets it wrong.
        if self.face.contents.face_flags & FT_FACE_FLAG_SFNT:
            name = FT_SfntName()
            for i in range(FT_Get_Sfnt_Name_Count(self.face)):
                result = FT_Get_Sfnt_Name(self.face, i, name)
                if result != 0:
                    continue
                if not (name.platform_id == TT_PLATFORM_MICROSOFT
                        and name.encoding_id == TT_MS_ID_UNICODE_CS):
                    continue
                if name.name_id == TT_NAME_ID_FONT_FAMILY:
                    string = string_at(name.string, name.string_len)
                    self.name = string.decode('utf-16be', 'ignore')
Esempio n. 5
0
 def from_fontconfig(cls, match):
     if match.face is not None:
         FT_Reference_Face(match.face)
         return cls(match.face)
     else:
         if not match.file:
             raise base.FontException('No filename for "%s"' % match.name)
         return cls.from_file(match.file)
Esempio n. 6
0
 def _get_bitmap_data(self):
     if self._mode == FT_PIXEL_MODE_MONO:
         # BCF fonts always render to 1 bit mono, regardless of render
         # flags. (freetype 2.3.5)
         self._convert_mono_to_gray_bitmap()
     elif self._mode == FT_PIXEL_MODE_GRAY:
         # Usual case
         assert self._glyph_slot.bitmap.num_grays == 256
         self._data = self._glyph_slot.bitmap.buffer
     else:
         raise base.FontException('Unsupported render mode for this glyph')
Esempio n. 7
0
    def __init__(self, data):
        self.buffer = (ctypes.c_byte * len(data))()
        ctypes.memmove(self.buffer, data, len(data))

        ft_library = ft_get_library()
        self.face = FT_Face()
        r = FT_New_Memory_Face(ft_library, self.buffer, len(self.buffer), 0,
                               self.face)
        if r != 0:
            raise base.FontException('Could not load font data')

        self.name = self.face.contents.family_name
        self.bold = self.face.contents.style_flags & FT_STYLE_FLAG_BOLD != 0
        self.italic = self.face.contents.style_flags & FT_STYLE_FLAG_ITALIC != 0
Esempio n. 8
0
 def _load_font_face_from_system(self):
     match = get_fontconfig().find_font(self.name, self.size, self.bold,
                                        self.italic)
     if not match:
         raise base.FontException('Could not match font "%s"' % self.name)
     self.face = FreeTypeFace.from_fontconfig(match)