/* Copyright (C) 2005 The cairomm Development Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #ifndef __CAIROMM_FONTFACE_H #define __CAIROMM_FONTFACE_H #include #include #include #include #include #include #ifdef CAIRO_HAS_FT_FONT #include #endif //CAIRO_HAS_FT_FONT namespace Cairo { class ScaledFont; class Context; /** * A FontFace represents a particular font at a particular weight, slant, and * other characteristic but no size, transformation, or size. * * Font faces are created using font-backend-specific constructors or implicitly * using the toy text API by way of Context::select_font_face(). The resulting * face can be accessed using Context::get_font_face(). */ class FontFace { protected: //TODO?: FontFace(cairo_font_face_t *target); public: /** Create a C++ wrapper for the C instance. This C++ instance should then be given to a RefPtr. * @param cobject The C instance. * @param has_reference Whether we already have a reference. Otherwise, the constructor will take an extra reference. */ explicit FontFace(cairo_font_face_t* cobject, bool has_reference = false); FontFace(const FontFace&) = delete; FontFace& operator=(const FontFace&) = delete; virtual ~FontFace(); /* Don't wrap these until we know what they are good for. void* get_user_data(const cairo_user_data_key_t *key); void set_user_data(const cairo_user_data_key_t *key, void *user_data, cairo_destroy_func_t destroy); */ /** * Returns the type of the backend used to create a font face */ FontType get_type() const; typedef cairo_font_face_t cobject; inline cobject* cobj() { return m_cobject; } inline const cobject* cobj() const { return m_cobject; } #ifndef DOXYGEN_IGNORE_THIS ///For use only by the cairomm implementation. inline ErrorStatus get_status() const { return cairo_font_face_status(const_cast(cobj())); } #endif //DOXYGEN_IGNORE_THIS void reference() const; void unreference() const; protected: cobject* m_cobject; }; /** @example toy-text.cc * A relatively simple example of using Cairo::ToyFontFace */ /** * A simple font face used for the cairo 'toy' font API. * @since 1.8 */ class ToyFontFace : public FontFace { public: /** * Creates a font face from a triplet of family, slant, and weight. These font * faces are used in implementation of the the Context "toy" font API. * * If family is the zero-length string "", the platform-specific default * family is assumed. The default family then can be queried using * get_family(). * * The Context::select_font_face() function uses this to create font faces. * See that function for limitations of toy font faces. * * @param family a font family name, encoded in UTF-8. * @param slant the slant for the font. * @param weight the weight for the font. */ static RefPtr create(const std::string& family, FontSlant slant, FontWeight weight); /** * Gets the familly name of a toy font. */ std::string get_family() const; /** * Gets the slant a toy font. */ FontSlant get_slant() const; /** * Gets the weight a toy font. */ FontWeight get_weight() const; protected: ToyFontFace(const std::string& family, FontSlant slant, FontWeight weight); }; /** @example user-font.cc * A relatively simple example of using Cairo::UserFontFace */ /** Font support with font data provided by the user. * * The user-font feature allows the cairo user to provide drawings for glyphs in * a font. This is most useful in implementing fonts in non-standard formats, * like SVG fonts and Flash fonts, but can also be used by games and other * application to draw "funky" fonts. * * To use user fonts, you must derive from this class and implement the virtual * functions below. The only virtual function that absolutely must be * implemented is render_glyph(). You should make the constructor protected and * provide a factory function that returns a new object in a RefPtr since it is * a refcounted object * * @code * class MyUserFont : public UserFontFace { * * public: * static Cairo::RefPtr create() { * return Cairo::RefPtr(new MyUserFont); * * protected: * // implement render_glyph() and any other virtual functions you want to override * ErrorStatus render_glyph(const RefPtr& scaled_font, * unsigned long glyph, * const RefPtr& cr, * TextExtents& metrics) { * // render the glyph into cr here * } * * MyUserFont() : UserFontFace() { * // constructor implementation * } * }; * @endcode * * @warning * Because of a design flaw in cairomm, it is currently necessary to keep the * the UserFontFace object around until as long as you are rendering text with * the user font. The following code illustrates the issue: * * @code * { * auto face = MyUserFont::create(); * cr->set_font_face(face); * } // scope for demonstration purposes * * // the following call will cause a crash because your user font is no longer * // in scope but it needs to call the virtual functions in face * cr->show_text("hello, world"); * @endcode * * The preceding is obviously a very contrived example, but the important thing * to know is that you *must* cache all userfont objects yourself as long as you * intend to render text with that font. A future release of cairomm will fix * this requirement, but that will require ABI-incompatible changes. * * @since 1.8 */ class UserFontFace : public FontFace { public: virtual ~UserFontFace(); /* static RefPtr create(); static RefPtr create(cairo_font_face_t* cobject, bool has_reference = false); */ protected: /** This function is called when a scaled-font needs to be created for a user * font-face. * * The Context @a cr is not used by the caller, but is prepared in font space, * similar to what the cairo contexts passed to the render_glyph method will * look like. The callback can use this context for extents computation for * example. After the callback is called, @a cr is checked for any error status. * * The @a extents argument is where the user font sets the font extents for * scaled_font. It is in font space, which means that for most cases its * ascent and descent members should add to 1.0. @a extents is preset to hold a * value of 1.0 for ascent, height, and max_x_advance, and 0.0 for descent and * max_y_advance members. * * The default implementation sets the font extents as described in the * previous paragraph. If you need different extents, you can override this * function in your derived class. * * Note that @a scaled_font is not fully initialized at this point and trying * to use it for text operations in the callback will result in deadlock. * * @param scaled_font the scaled-font being created * @param cr cairo context, in font space * @param extents extents to fill in, in font space * @return CAIRO_STATUS_SUCCESS upon success, or CAIRO_STATUS_USER_FONT_ERROR or any other error status on error. * * @since 1.8 */ virtual ErrorStatus init(const RefPtr& scaled_font, const RefPtr& cr, FontExtents& extents); /** This function is called to convert an input Unicode character to a single * glyph. This is used by the Context::show_text() operation. * * This function is used to provide the same functionality as the * text_to_glyphs callback does but has much less control on the output, in * exchange for increased ease of use. The inherent assumption to using this * callback is that each character maps to one glyph, and that the mapping is * context independent. It also assumes that glyphs are positioned according * to their advance width. These mean no ligatures, kerning, or complex * scripts can be implemented using this callback. * * The default implementation of this function is an identity mapping from * Unicode code-points to glyph indices. If you need different behavior, you * may override this virtual function in your derived class. * * Note: While cairo does not impose any limitation on glyph indices, some * applications may assume that a glyph index fits in a 16-bit unsigned * integer. As such, it is advised that user-fonts keep their glyphs in the 0 * to 65535 range. Furthermore, some applications may assume that glyph 0 is a * special glyph-not-found glyph. User-fonts are advised to use glyph 0 for * such purposes and do not use that glyph value for other purposes. * * @param scaled_font the scaled-font being created * @param unicode input unicode character code-point * @param glyph_index output glyph index * @return CAIRO_STATUS_SUCCESS upon success, or CAIRO_STATUS_USER_FONT_ERROR or any other error status on error. * @since 1.8 */ virtual ErrorStatus unicode_to_glyph(const RefPtr& scaled_font, unsigned long unicode, unsigned long& glyph); /** This function is called when a user scaled-font needs to render a * glyph. * * You must implement this in your derived class, and it is expected to draw * the glyph with code @a glyph to the Context @a cr. @a cr is prepared such * that the glyph drawing is done in font space. That is, the matrix set on @a * cr is the scale matrix of @a scaled_font, The @a extents argument is where * the user font sets the font extents for scaled_font. However, if user * prefers to draw in user space, they can achieve that by changing the matrix * on @a cr. All cairo rendering operations to @a cr are permitted, however, * the result is undefined if any source other than the default source on @a * cr is used. That means, glyph bitmaps should be rendered using * Context::mask() instead of Context::paint(). * * Other non-default settings on @a cr include a font size of 1.0 (given that * it is set up to be in font space), and font options corresponding to @a * scaled_font. * * The @a extents argument is preset to have x_bearing, width, and y_advance * of zero, y_bearing set to -font_extents.ascent, height to * font_extents.ascent+font_extents.descent, and x_advance to * font_extents.max_x_advance. The only field user needs to set in majority of * cases is x_advance. If the width field is zero upon this function returning * (which is its preset value), the glyph extents are automatically computed * based on the drawings done to @a cr. This is in most cases exactly what the * desired behavior is. However, if for any reason this function sets the * extents, it must be ink extents, and include the extents of all drawing * done to @a cr. * * @param scaled_font user scaled-font * @param glyph glyph code to render * @param cr Context to draw to, in font space * @param extents glyph extents to fill in, in font space * @return CAIRO_STATUS_SUCCESS upon success, or CAIRO_STATUS_USER_FONT_ERROR or any other error status on error. * * @since 1.8 */ virtual ErrorStatus render_glyph(const RefPtr& scaled_font, unsigned long glyph, const RefPtr& cr, TextExtents& metrics) = 0; /** This function is called to convert input text to an array of glyphs. This * is used by the Context::show_text() operation. * * Using this function, the user-font has full control on glyphs and their * positions. That means, it allows for features like ligatures and kerning, * as well as complex shaping required for scripts like Arabic and Indic. * * This function should populate the glyph indices and positions (in font * space) assuming that the text is to be shown at the origin. * * If clusters is not empty, cluster mapping should be computed. * * If you do not override this virtual function in your derived class, * the unicode_to_glyph function is used instead. * * Note: While cairo does not impose any limitation on glyph indices, some * applications may assume that a glyph index fits in a 16-bit unsigned * integer. As such, it is advised that user-fonts keep their glyphs in the 0 * to 65535 range. Furthermore, some applications may assume that glyph 0 is a * special glyph-not-found glyph. User-fonts are advised to use glyph 0 for * such purposes and do not use that glyph value for other purposes. * * @param scaled_font the scaled-font being created * @param utf8 a string of text encoded in UTF-8 * @param glyphs array of glyphs to fill, in font space * @param clusters array of cluster mapping information to fill * @param cluster_flags a variable to set the cluster flags corresponding to the output clusters * @return CAIRO_STATUS_SUCCESS upon success, or CAIRO_STATUS_USER_FONT_ERROR or any other error status on error. * @since 1.8 */ virtual ErrorStatus text_to_glyphs(const RefPtr& scaled_font, const std::string& utf8, std::vector& glyphs, std::vector& clusters, TextClusterFlags& cluster_flags); UserFontFace(); private: static cairo_status_t init_cb(cairo_scaled_font_t* scaled_font, cairo_t *cr, cairo_font_extents_t* metrics); static cairo_status_t unicode_to_glyph_cb(cairo_scaled_font_t *scaled_font, unsigned long unicode, unsigned long *glyph); static cairo_status_t render_glyph_cb(cairo_scaled_font_t *scaled_font, unsigned long glyph, cairo_t *cr, cairo_text_extents_t *metrics); static cairo_status_t text_to_glyphs_cb (cairo_scaled_font_t *scaled_font, const char *utf8, int utf8_len, cairo_glyph_t **glyphs, int *num_glyphs, cairo_text_cluster_t **clusters, int *num_clusters, cairo_text_cluster_flags_t *cluster_flags); }; // font system support #ifdef CAIRO_HAS_FT_FONT class FtFontFace : public FontFace { public: /** Creates a new font face for the FreeType font backend from a pre-opened * FreeType face. This font can then be used with Context::set_font_face() or * FtScaledFont::create(). * * As an example, here is how one might correctly couple the lifetime of the * FreeType face object to the FtFontFace: * @code * static const cairo_user_data_key_t key; * font_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0); * status = cairo_font_face_set_user_data (font_face, &key, * ft_face, (cairo_destroy_func_t) FT_Done_Face); * if (status) { * cairo_font_face_destroy (font_face); * FT_Done_Face (ft_face); * return ERROR; * } * @endcode * * @param face A FreeType face object, already opened. This must be kept * around until the face's ref_count drops to zero and it is freed. Since the * face may be referenced internally to Cairo, the best way to determine when * it is safe to free the face is to pass a cairo_destroy_func_t to * cairo_font_face_set_user_data(). * @param load_flags flags to pass to FT_Load_Glyph when loading glyphs from * the font. These flags are OR'ed together with the flags derived from the * cairo_font_options_t passed to cairo_scaled_font_create(), so only a few * values such as FT_LOAD_VERTICAL_LAYOUT, and FT_LOAD_FORCE_AUTOHINT are * useful. You should not pass any of the flags affecting the load target, * such as FT_LOAD_TARGET_LIGHT. * * @since 1.8 */ static RefPtr create(FT_Face face, int load_flags); //TODO: Add a suitable default value for load_flags? #ifdef CAIRO_HAS_FC_FONT /** Creates a new font face for the FreeType font backend based on a * fontconfig pattern. This font can then be used with Context::set_font_face() * or FtScaledFont::create(). * * Font rendering options are represented both here and when you call * FtScaledFont::create(). Font options that have a representation in a * FcPattern must be passed in here; to modify FcPattern appropriately to * reflect the options in a FontOptions, call FontOptions::substitute(). * * The pattern's FC_FT_FACE element is inspected first and if that is set, * that will be the FreeType font face associated with the returned cairo font * face. Otherwise the FC_FILE and FC_INDEX elements of pattern are used to * load a font face from file. * * If the FC_FT_FACE element of pattern is set, the user is responsible for * making sure that the referenced FT_Face remains valid for the life time of * the returned FtFontFace. See FtFontFace::create() for an exmaple of how to * couple the life time of the FT_Face to that of the cairo font-face. * * @param pattern A fully resolved fontconfig pattern. A pattern can be * resolved, by, among other things, calling FcConfigSubstitute(), * FcDefaultSubstitute(), then FcFontMatch(). Cairo will call * FcPatternReference() on this pattern, so you should not further modify the * pattern, but you can release your reference to the pattern with * FcPatternDestroy() if you no longer need to access it. * * @since 1.8 */ static RefPtr create(FcPattern* pattern); #endif // CAIRO_HAS_FC_FONT /** Sets synthesis options to control how FreeType renders the glyphs for a * particular font face. The given options are ORed with the currently active * options. * * @param synth_flags A set of synthesis options to enable * @since 1.12 */ void set_synthesize(FtSynthesize synth_flags); /** Unsets the specified FreeType glypth synthesis options * * @param synth_flags A set of synthesis options to disable * @since 1.12 */ void unset_synthesize(FtSynthesize synth_flags); /** Returns currently activy FreeType glyph synthesis options * * @since 1.12 */ FtSynthesize get_synthesize() const; protected: FtFontFace(FT_Face face, int load_flags); #ifdef CAIRO_HAS_FC_FONT FtFontFace(FcPattern* pattern); #endif // CAIRO_HAS_FC_FONT }; #endif // CAIRO_HAS_FT_FONT } // namespace Cairo #endif //__CAIROMM_FONTFACE_H // vim: ts=2 sw=2 et