/* -*- mode: c++; c-basic-offset: 4 -*- */ /* A python interface to FreeType */ #pragma once #ifndef MPL_FT2FONT_H #define MPL_FT2FONT_H #include <vector> #include <stdint.h> #include <unordered_map> extern "C" { #include <ft2build.h> #include FT_FREETYPE_H #include FT_GLYPH_H #include FT_OUTLINE_H #include FT_SFNT_NAMES_H #include FT_TYPE1_TABLES_H #include FT_TRUETYPE_TABLES_H } #define PY_SSIZE_T_CLEAN #include <Python.h> /* By definition, FT_FIXED as 2 16bit values stored in a single long. */ #define FIXED_MAJOR(val) (signed short)((val & 0xffff0000) >> 16) #define FIXED_MINOR(val) (unsigned short)(val & 0xffff) // the FreeType string rendered into a width, height buffer class FT2Image { public: FT2Image(); FT2Image(unsigned long width, unsigned long height); virtual ~FT2Image(); void resize(long width, long height); void draw_bitmap(FT_Bitmap *bitmap, FT_Int x, FT_Int y); void draw_rect(unsigned long x0, unsigned long y0, unsigned long x1, unsigned long y1); void draw_rect_filled(unsigned long x0, unsigned long y0, unsigned long x1, unsigned long y1); unsigned char *get_buffer() { return m_buffer; } unsigned long get_width() { return m_width; } unsigned long get_height() { return m_height; } private: bool m_dirty; unsigned char *m_buffer; unsigned long m_width; unsigned long m_height; // prevent copying FT2Image(const FT2Image &); FT2Image &operator=(const FT2Image &); }; extern FT_Library _ft2Library; class FT2Font { public: FT2Font(FT_Open_Args &open_args, long hinting_factor, std::vector<FT2Font *> &fallback_list); virtual ~FT2Font(); void clear(); void set_size(double ptsize, double dpi); void set_charmap(int i); void select_charmap(unsigned long i); void set_text( size_t N, uint32_t *codepoints, double angle, FT_Int32 flags, std::vector<double> &xys); int get_kerning(FT_UInt left, FT_UInt right, FT_UInt mode, bool fallback); int get_kerning(FT_UInt left, FT_UInt right, FT_UInt mode, FT_Vector &delta); void set_kerning_factor(int factor); void load_char(long charcode, FT_Int32 flags, FT2Font *&ft_object, bool fallback); bool load_char_with_fallback(FT2Font *&ft_object_with_glyph, FT_UInt &final_glyph_index, std::vector<FT_Glyph> &parent_glyphs, std::unordered_map<long, FT2Font *> &parent_char_to_font, std::unordered_map<FT_UInt, FT2Font *> &parent_glyph_to_font, long charcode, FT_Int32 flags, FT_Error &charcode_error, FT_Error &glyph_error, bool override); void load_glyph(FT_UInt glyph_index, FT_Int32 flags, FT2Font *&ft_object, bool fallback); void load_glyph(FT_UInt glyph_index, FT_Int32 flags); void get_width_height(long *width, long *height); void get_bitmap_offset(long *x, long *y); long get_descent(); // TODO: Since we know the size of the array upfront, we probably don't // need to dynamically allocate like this void get_xys(bool antialiased, std::vector<double> &xys); void draw_glyphs_to_bitmap(bool antialiased); void draw_glyph_to_bitmap(FT2Image &im, int x, int y, size_t glyphInd, bool antialiased); void get_glyph_name(unsigned int glyph_number, char *buffer, bool fallback); long get_name_index(char *name); FT_UInt get_char_index(FT_ULong charcode, bool fallback); PyObject* get_path(); bool get_char_fallback_index(FT_ULong charcode, int& index) const; FT_Face const &get_face() const { return face; } FT2Image &get_image() { return image; } FT_Glyph const &get_last_glyph() const { return glyphs.back(); } size_t get_last_glyph_index() const { return glyphs.size() - 1; } size_t get_num_glyphs() const { return glyphs.size(); } long get_hinting_factor() const { return hinting_factor; } FT_Bool has_kerning() const { return FT_HAS_KERNING(face); } private: FT2Image image; FT_Face face; FT_Vector pen; /* untransformed origin */ std::vector<FT_Glyph> glyphs; std::vector<FT2Font *> fallbacks; std::unordered_map<FT_UInt, FT2Font *> glyph_to_font; std::unordered_map<long, FT2Font *> char_to_font; FT_BBox bbox; FT_Pos advance; long hinting_factor; int kerning_factor; // prevent copying FT2Font(const FT2Font &); FT2Font &operator=(const FT2Font &); }; #endif