From cca66b9ec4e494c1d919bff0f71a820d8afab1fa Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 20:24:48 +0200 Subject: Adding upstream version 1.2.2. Signed-off-by: Daniel Baumann --- src/libnrtype/font-lister.h | 364 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 364 insertions(+) create mode 100644 src/libnrtype/font-lister.h (limited to 'src/libnrtype/font-lister.h') diff --git a/src/libnrtype/font-lister.h b/src/libnrtype/font-lister.h new file mode 100644 index 0000000..5d73119 --- /dev/null +++ b/src/libnrtype/font-lister.h @@ -0,0 +1,364 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#ifndef FONT_LISTER_H +#define FONT_LISTER_H + +/* + * Font selection widgets + * + * Authors: + * Chris Lahey + * Lauris Kaplinski + * Tavmjong Bah + * + * Copyright (C) 1999-2001 Ximian, Inc. + * Copyright (C) 2002 Lauris Kaplinski + * Copyright (C) 2013 Tavmjong Bah + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include +#include + +#include +#include // For strescape() + +#include +#include +#include + +class SPObject; +class SPDocument; +class SPCSSAttr; +class SPStyle; + +namespace Gtk { +class CellRenderer; +} + +namespace Inkscape { + +/** + * This class enumerates fonts using libnrtype into reusable data stores and + * allows for random access to the font-family list and the font-style list. + * Setting the font-family updates the font-style list. "Style" in this case + * refers to everything but family and size (e.g. italic/oblique, weight). + * + * This class handles font-family lists and fonts that are not on the system, + * where there is not an entry in the fontInstanceMap. + * + * This class uses the idea of "font_spec". This is a plain text string as used by + * Pango. It is similar to the CSS font shorthand except that font-family comes + * first and in this class the font-size is not used. + * + * This class uses the FontFactory class to get a list of system fonts + * and to find best matches via Pango. The Pango interface is only setup + * to deal with fonts that are on the system so care must be taken. For + * example, best matches should only be done with the first font-family + * in a font-family list. If the first font-family is not on the system + * then a generic font-family should be used (sans-serif -> Sans). + * + * This class is used by the UI interface (text-toolbar, font-select, etc.). + * Those items can change the selected font family and style here. When that + * happens. this class emits a signal for those items to update their displayed + * values. + * + * This class is a singleton (one instance per Inkscape session). Since fonts + * used in a document are added to the list, there really should be one + * instance per document. + * + * "Font" includes family and style. It should not be used when one + * means font-family. + */ + +class FontLister { +public: + enum Exceptions { + FAMILY_NOT_FOUND, + STYLE_NOT_FOUND + }; + + virtual ~FontLister(); + + /** + * GtkTreeModelColumnRecord for the font-family list Gtk::ListStore + */ + struct FontListClass : public Gtk::TreeModelColumnRecord { + /** + * Column containing the family name + */ + Gtk::TreeModelColumn family; + + /** + * Column containing the styles for each family name. + */ + Gtk::TreeModelColumn styles; + + /** + * Column containing flag if font is on system + */ + Gtk::TreeModelColumn onSystem; + + /** + * Not actually a column. + * Necessary for quick initialization of FontLister, + * we initially store the pango family and if the + * font style is actually used we'll cache it in + * %styles. + */ + Gtk::TreeModelColumn pango_family; + + FontListClass() + { + add(family); + add(styles); + add(onSystem); + add(pango_family); + } + }; + + FontListClass FontList; + + struct FontStyleListClass : public Gtk::TreeModelColumnRecord { + /** + * Column containing the styles as Font designer used. + */ + Gtk::TreeModelColumn displayStyle; + + /** + * Column containing the styles in CSS/Pango format. + */ + Gtk::TreeModelColumn cssStyle; + + FontStyleListClass() + { + add(cssStyle); + add(displayStyle); + } + }; + + FontStyleListClass FontStyleList; + + /** + * @return the ListStore with the family names + * + * The return is const and the function is declared as const. + * The ListStore is ready to be used after class instantiation + * and should not be modified. + */ + const Glib::RefPtr get_font_list() const; + + /** + * @return the ListStore with the styles + */ + const Glib::RefPtr get_style_list() const; + + /** + * Inserts a font family or font-fallback list (for use when not + * already in document or on system). + */ + void insert_font_family(Glib::ustring new_family); + + /** + * Updates font list to include fonts in document. + */ + void update_font_list(SPDocument *document); + +public: + static Inkscape::FontLister *get_instance(); + + /** + * Takes a hand written font spec and returns a Pango generated one in + * standard form. + */ + Glib::ustring canonize_fontspec(Glib::ustring fontspec); + + /** + * Find closest system font to given font. + */ + Glib::ustring system_fontspec(Glib::ustring fontspec); + + /** + * Gets font-family and style from fontspec. + * font-family and style returned. + */ + std::pair ui_from_fontspec(Glib::ustring fontspec); + + /** + * Sets font-family and style after a selection change. + * New font-family and style returned. + */ + std::pair selection_update(); + + /** + * Sets current_fontspec, etc. If check is false, won't + * try to find best style match (assumes style in fontspec + * valid for given font-family). + */ + void set_fontspec(Glib::ustring fontspec, bool check = true); + + Glib::ustring get_fontspec() { return (canonize_fontspec(current_family + ", " + current_style)); } + + /** + * Changes font-family, updating style list and attempting to find + * closest style to current_style style (if check_style is true). + * New font-family and style returned. + * Does NOT update current_family and current_style. + * (For potential use in font-selector which doesn't update until + * "Apply" button clicked.) + */ + std::pair new_font_family(Glib::ustring family, bool check_style = true); + + /** + * Sets font-family, updating style list and attempting + * to find closest style to old current_style. + * New font-family and style returned. + * Updates current_family and current_style. + * Calls new_font_family(). + * (For use in text-toolbar where update is immediate.) + */ + std::pair set_font_family(Glib::ustring family, bool check_style = true, + bool emit = true); + + /** + * Sets font-family from row in list store. + * The row can be used to determine if we are in the + * document or system part of the font-family list. + * This is needed to handle scrolling through the + * font-family list correctly. + * Calls set_font_family(). + */ + std::pair set_font_family(int row, bool check_style = true, bool emit = true); + + Glib::ustring get_font_family() + { + return current_family; + } + + int get_font_family_row() + { + return current_family_row; + } + + /** + * Sets style. Does not validate style for family. + */ + void set_font_style(Glib::ustring style, bool emit = true); + + Glib::ustring get_font_style() + { + return current_style; + } + + Glib::ustring fontspec_from_style(SPStyle *style); + + /** + * Fill css using given fontspec (doesn't need to be member function). + */ + void fill_css(SPCSSAttr *css, Glib::ustring fontspec = ""); + + Gtk::TreeModel::Row get_row_for_font() { return get_row_for_font (current_family); } + + Gtk::TreeModel::Row get_row_for_font(Glib::ustring family); + + Gtk::TreePath get_path_for_font(Glib::ustring family); + + bool is_path_for_font(Gtk::TreePath path, Glib::ustring family); + + Gtk::TreeModel::Row get_row_for_style() { return get_row_for_style (current_style); } + + Gtk::TreeModel::Row get_row_for_style(Glib::ustring style); + + Gtk::TreePath get_path_for_style(Glib::ustring style); + + std::pair get_paths(Glib::ustring family, Glib::ustring style); + + /** + * Return best style match for new font given style for old font. + */ + Glib::ustring get_best_style_match(Glib::ustring family, Glib::ustring style); + + /** + * Ensures the style list for a particular family has been created. + */ + void ensureRowStyles(Glib::RefPtr model, Gtk::TreeModel::iterator const iter); + + /** + * Get markup for font-family. + */ + Glib::ustring get_font_family_markup(Gtk::TreeIter const &iter); + + /** + * Let users of FontLister know to update GUI. + * This is to allow synchronization of changes across multiple widgets. + * Handlers should block signals. + * Input is fontspec to set. + */ + sigc::connection connectUpdate(sigc::slot slot) { + return update_signal.connect(slot); + } + + bool blocked() { return block; } + +private: + FontLister(); + + void update_font_data_recursive(SPObject& r, std::map> &font_data); + + void font_family_row_update(int start=0); + + Glib::RefPtr font_list_store; + Glib::RefPtr style_list_store; + + /** + * Info for currently selected font (what is shown in the UI). + * May include font-family lists and fonts not on system. + */ + int current_family_row; + Glib::ustring current_family; + Glib::ustring current_style; + + /** + * If a font-family is not on system, this list of styles is used. + */ + GList *default_styles; + + bool block; + void emit_update(); + sigc::signal update_signal; +}; + +} // namespace Inkscape + +// Helper functions +bool font_lister_separator_func (const Glib::RefPtr& model, + const Gtk::TreeModel::iterator& iter); + +gboolean font_lister_separator_func2(GtkTreeModel *model, + GtkTreeIter *iter, + gpointer /*data*/); + +void font_lister_cell_data_func (Gtk::CellRenderer *renderer, Gtk::TreeIter const &iter); + +void font_lister_cell_data_func_markup (Gtk::CellRenderer *renderer, Gtk::TreeIter const &iter); + +void font_lister_cell_data_func2(GtkCellLayout * /*cell_layout*/, + GtkCellRenderer *cell, + GtkTreeModel *model, + GtkTreeIter *iter, + gpointer /*data*/); + +void font_lister_style_cell_data_func (Gtk::CellRenderer *renderer, Gtk::TreeIter const &iter); + +#endif + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 : -- cgit v1.2.3