14#include <boost/algorithm/string.hpp>
16#include <glibmm/refptr.h>
17#include <glibmm/ustring.h>
18#include <gtkmm/adjustment.h>
19#include <gtkmm/enums.h>
20#include <gtkmm/object.h>
21#include <gtkmm/sizegroup.h>
22#include <gtkmm/spinbutton.h>
28#include <glibmm/i18n.h>
46std::pair<Glib::ustring, Glib::ustring>
get_axis_name(
const std::string& tag,
const Glib::ustring& abbr) {
51 static std::map<std::string, std::pair<Glib::ustring, Glib::ustring>>
map = {
54 {
"GRAD", std::make_pair(C_(
"Variable font axis",
"Grade"), _(
"Alter stroke thicknesses (or other forms) without affecting the type’s overall width"))},
57 {
"XOPQ", std::make_pair(C_(
"Variable font axis",
"X opaque"), _(
"Alter the opaque stroke forms of glyphs in the X dimension"))},
60 {
"YOPQ", std::make_pair(C_(
"Variable font axis",
"Y opaque"), _(
"Alter the opaque stroke forms of glyphs in the Y dimension"))},
64 {
"XTRA", std::make_pair(C_(
"Variable font axis",
"X transparent"), _(
"Alter the transparent spaces inside and around all glyphs along the X dimension"))},
65 {
"YTRA", std::make_pair(C_(
"Variable font axis",
"Y transparent"), _(
"Alter the transparent spaces inside and around all glyphs along the Y dimension"))},
67 {
"XTCH", std::make_pair(C_(
"Variable font axis",
"X transparent Chinese"), _(
"Alter the width of Chinese glyphs"))},
68 {
"YTCH", std::make_pair(C_(
"Variable font axis",
"Y transparent Chinese"), _(
"Alter the height of Chinese glyphs"))},
70 {
"YTLC", std::make_pair(C_(
"Variable font axis",
"Lowercase height"), _(
"Vary the height of counters and other spaces between the baseline and x-height"))},
72 {
"YTUC", std::make_pair(C_(
"Variable font axis",
"Uppercase height"), _(
"Vary the height of uppercase letterforms"))},
74 {
"YTAS", std::make_pair(C_(
"Variable font axis",
"Ascender height"), _(
"Vary the height of lowercase ascenders"))},
76 {
"YTDE", std::make_pair(C_(
"Variable font axis",
"Descender depth"), _(
"Vary the depth of lowercase descenders"))},
78 {
"YTFI", std::make_pair(C_(
"Variable font axis",
"Figure height"), _(
"Vary the height of figures"))},
80 {
"YTSE", std::make_pair(C_(
"Variable font axis",
"Serif rise"), _(
"Vary the shape of the serifs"))},
82 {
"FLAR", std::make_pair(C_(
"Variable font axis",
"Flare"), _(
"Controls the flaring of the stems"))},
85 {
"VOLM", std::make_pair(C_(
"Variable font axis",
"Volume"), _(
"Volume works in combination with flare to transform serifs"))},
87 {
"SOFT", std::make_pair(C_(
"Variable font axis",
"Softness"), _(
"Softness makes letterforms more soft and rounded"))},
89 {
"CASL", std::make_pair(C_(
"Variable font axis",
"Casual"), _(
"Adjust the letterforms from a more serious style to a more casual style"))},
91 {
"CRSV", std::make_pair(C_(
"Variable font axis",
"Cursive"), _(
"Control the substitution of cursive forms"))},
93 {
"FILL", std::make_pair(C_(
"Variable font axis",
"Fill"), _(
"Fill can turn transparent forms opaque"))},
95 {
"MONO", std::make_pair(C_(
"Variable font axis",
"Monospace"), _(
"Adjust the glyphs from a proportional width to a fixed width"))},
97 {
"WONK", std::make_pair(C_(
"Variable font axis",
"Wonky"), _(
"Binary switch used to control substitution of “wonky” forms"))},
99 {
"ESHP", std::make_pair(C_(
"Variable font axis",
"Element shape"), _(
"Selection of the base element glyphs are composed of"))},
101 {
"EGRD", std::make_pair(C_(
"Variable font axis",
"Element grid"), _(
"Controls how many elements are used per one grid unit"))},
106 {
"opsz", std::make_pair(C_(
"Variable font axis",
"Optical size"), _(
"Optimize the typeface for use at specific size"))},
108 {
"slnt", std::make_pair(C_(
"Variable font axis",
"Slant"), _(
"Controls the font file’s slant parameter for oblique styles"))},
110 {
"ital", std::make_pair(C_(
"Variable font axis",
"Italic"), _(
"Turns on the font’s italic forms"))},
112 {
"wght", std::make_pair(C_(
"Variable font axis",
"Weight"), _(
"Controls the font file’s weight parameter"))},
114 {
"wdth", std::make_pair(C_(
"Variable font axis",
"Width"), _(
"Controls the font file’s width parameter"))},
116 {
"xtab", std::make_pair(C_(
"Variable font axis",
"Tabular width"), _(
"Controls the tabular width"))},
117 {
"udln", std::make_pair(C_(
"Variable font axis",
"Underline"), _(
"Controls the weight of an underline"))},
118 {
"shdw", std::make_pair(C_(
"Variable font axis",
"Shadow"), _(
"Controls the depth of a shadow"))},
119 {
"refl", std::make_pair(C_(
"Variable font axis",
"Reflection"), _(
"Controls the Y reflection"))},
120 {
"otln", std::make_pair(C_(
"Variable font axis",
"Outline"), _(
"Controls the weight of a font’s outline"))},
121 {
"engr", std::make_pair(C_(
"Variable font axis",
"Engrave"), _(
"Controls the width of an engraving"))},
122 {
"embo", std::make_pair(C_(
"Variable font axis",
"Emboss"), _(
"Controls the depth of an emboss"))},
123 {
"rxad", std::make_pair(C_(
"Variable font axis",
"Relative X advance"), _(
"Controls the relative X advance - horizontal motion of the glyph"))},
124 {
"ryad", std::make_pair(C_(
"Variable font axis",
"Relative Y advance"), _(
"Controls the relative Y advance - vertical motion of the glyph"))},
125 {
"rsec", std::make_pair(C_(
"Variable font axis",
"Relative second"), _(
"Controls the relative second value - as in one second of animation time"))},
126 {
"vrot", std::make_pair(C_(
"Variable font axis",
"Rotation"), _(
"Controls the rotation of the glyph in degrees"))},
127 {
"vuid", std::make_pair(C_(
"Variable font axis",
"Unicode variation"), _(
"Controls the glyph’s unicode ID"))},
128 {
"votf", std::make_pair(C_(
"Variable font axis",
"Feature variation"), _(
"Controls the glyph’s feature variation"))},
131 auto it =
map.find(tag);
134 it =
map.find(boost::algorithm::to_lower_copy(tag));
138 it =
map.find(boost::algorithm::to_upper_copy(tag));
144 return std::make_pair(abbr,
"");
161 label = Gtk::make_managed<Gtk::Label>(label_ +
":");
162 label->set_tooltip_text(tooltip);
163 label->set_xalign(0.0f);
166 edit = Gtk::make_managed<Gtk::SpinButton>();
167 edit->set_max_width_chars(5);
168 edit->set_valign(Gtk::Align::CENTER);
169 edit->set_margin_top(2);
170 edit->set_margin_bottom(2);
171 edit->set_tooltip_text(tooltip);
180 adj->set_step_increment(step);
181 adj->set_page_increment(step * 10.0);
182 edit->set_adjustment(adj);
186 adj_scale->set_step_increment(step);
187 adj_scale->set_page_increment(step * 10.0);
188 scale = Gtk::make_managed<Gtk::Scale>();
190 scale->set_hexpand(
true);
191 scale->set_adjustment(adj_scale);
192 scale->get_style_context()->add_class(
"small-slider");
193 scale->set_draw_value(
false);
197 g_object_bind_property(adj->gobj(),
"value", adj_scale->gobj(),
"value", GBindingFlags(G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL));
204 scale->get_adjustment()->set_value(value);
214 set_name(
"FontVariations");
215 _size_group = Gtk::SizeGroup::create(Gtk::SizeGroup::Mode::HORIZONTAL);
216 _size_group_edit = Gtk::SizeGroup::create(Gtk::SizeGroup::Mode::HORIZONTAL);
223 const auto& axes = res ? res->get_opentype_varaxes() : std::map<Glib::ustring, OTVarAxis>();
225 bool rebuild =
false;
233 if (identical)
return;
235 bool same_def = std::equal(begin(axes),
end(axes), begin(
_open_type_axes), [=](
const auto& a,
const auto& b){
236 return a.first == b.first && a.second.same_definition(b.second);
240 if (!same_def) rebuild =
true;
251 auto it = begin(axes);
252 for (
auto& axis :
_axes) {
253 if (it !=
end(axes) && axis->get_name() == it->first) {
254 const auto eps = 0.00001;
255 if (abs(axis->get_value() - it->second.set_val) > eps) {
256 axis->set_value(it->second.set_val);
260 g_message(
"axis definition mismatch '%s'", axis->get_name().c_str());
273 for (
auto child : children) {
283 for (
const auto& a : ot_axes) {
286 auto axis = Gtk::make_managed<FontVariationAxis>(a.first, a.second, label_tooltip.first, label_tooltip.second);
287 _axes.push_back(axis);
291 axis->get_editbox()->get_adjustment()->signal_value_changed().connect(
309 Glib::ustring css_string;
311 for (
auto axis: axes) {
312 Glib::ustring
name = axis->get_name();
316 if (
name ==
"Weight")
name =
"wght";
317 if (
name ==
"OpticalSize")
name =
"opsz";
319 if (
name ==
"Italic")
name =
"ital";
321 std::stringstream value;
322 value << std::fixed << std::setprecision(axis->get_precision()) << axis->get_value();
323 css_string +=
"'" +
name +
"' " + value.str() +
"', ";
333 Glib::ustring pango_string;
335 if (!
_axes.empty()) {
339 for (
const auto& axis:
_axes) {
340 if (!include_defaults && axis->get_value() == axis->get_def())
continue;
341 Glib::ustring
name = axis->get_name();
345 if (
name ==
"Weight")
name =
"wght";
346 if (
name ==
"OpticalSize")
name =
"opsz";
348 if (
name ==
"Italic")
name =
"ital";
351 str << std::fixed << std::setprecision(axis->get_precision()) << axis->get_value();
352 pango_string +=
name +
"=" + str.
str() +
",";
355 pango_string.erase (pango_string.size() - 1);
362 return !
_axes.empty();
369 default:
return Glib::RefPtr<Gtk::SizeGroup>();
gfloat magnitude(const vector_type)
std::shared_ptr< FontInstance > FaceFromFontSpecification(char const *fontSpecification)
A thin wrapper around std::ostringstream, but writing floating point numbers in the format required b...
static FontFactory & get(Args &&... args)
TODO: insert short description here.
std::shared_ptr< Css const > css
std::unordered_map< std::string, std::unique_ptr< SPDocument > > map
TODO: insert short description here.
The data describing a single loaded font.
std::vector< Gtk::Widget * > get_children(Gtk::Widget &widget)
Get a vector of the widgetʼs children, from get_first_child() through each get_next_sibling().
Helper class to stream background task notifications as a series of messages.
static void append(std::vector< T > &target, std::vector< T > &&source)
void sp_repr_css_set_property(SPCSSAttr *css, gchar const *name, gchar const *value)
Set a style property to a new value (e.g.
void remove(std::vector< T > &vec, T const &val)