Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
sp-font.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * SVG <font> element implementation
4 *
5 * Author:
6 * Felipe C. da S. Sanches <juca@members.fsf.org>
7 * Abhishek Sharma
8 *
9 * Copyright (C) 2008, Felipe C. da S. Sanches
10 *
11 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
12 */
13
14#include "sp-font.h"
15
16#include "attributes.h" // for SPAttr
17#include "document.h" // for SPDocument
18#include "sp-glyph.h" // for SPGlyph
19
20#include "object/sp-object.h" // for SPObject, SP_OBJ...
21#include "xml/document.h" // for Document
22#include "xml/node.h" // for Node
23
24
25//I think we should have extra stuff here and in the set method in order to set default value as specified at http://www.w3.org/TR/SVG/fonts.html
26
27// TODO determine better values and/or make these dynamic:
28double FNT_DEFAULT_ADV = 1024; // TODO determine proper default
29double FNT_DEFAULT_ASCENT = 768; // TODO determine proper default
30double FNT_UNITS_PER_EM = 1024; // TODO determine proper default
31
40
41SPFont::~SPFont() = default;
42
55
64
65
71
72 if (!_block) this->parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
73}
74
76 this->document->removeResource("font", this);
77
79}
80
81void SPFont::set(SPAttr key, const gchar *value) {
82 // TODO these are floating point, so some epsilon comparison would be good
83 switch (key) {
85 {
86 double number = value ? g_ascii_strtod(value, nullptr) : 0;
87
88 if (number != this->horiz_origin_x){
89 this->horiz_origin_x = number;
90 this->requestModified(SP_OBJECT_MODIFIED_FLAG);
91 }
92 break;
93 }
95 {
96 double number = value ? g_ascii_strtod(value, nullptr) : 0;
97
98 if (number != this->horiz_origin_y){
99 this->horiz_origin_y = number;
100 this->requestModified(SP_OBJECT_MODIFIED_FLAG);
101 }
102 break;
103 }
105 {
106 double number = value ? g_ascii_strtod(value, nullptr) : FNT_DEFAULT_ADV;
107
108 if (number != this->horiz_adv_x){
109 this->horiz_adv_x = number;
110 this->requestModified(SP_OBJECT_MODIFIED_FLAG);
111 }
112 break;
113 }
115 {
116 double number = value ? g_ascii_strtod(value, nullptr) : FNT_DEFAULT_ADV / 2.0;
117
118 if (number != this->vert_origin_x){
119 this->vert_origin_x = number;
120 this->requestModified(SP_OBJECT_MODIFIED_FLAG);
121 }
122 break;
123 }
125 {
126 double number = value ? g_ascii_strtod(value, nullptr) : FNT_DEFAULT_ASCENT;
127
128 if (number != this->vert_origin_y){
129 this->vert_origin_y = number;
130 this->requestModified(SP_OBJECT_MODIFIED_FLAG);
131 }
132 break;
133 }
135 {
136 double number = value ? g_ascii_strtod(value, nullptr) : FNT_UNITS_PER_EM;
137
138 if (number != this->vert_adv_y){
139 this->vert_adv_y = number;
140 this->requestModified(SP_OBJECT_MODIFIED_FLAG);
141 }
142 break;
143 }
144 default:
145 SPObject::set(key, value);
146 break;
147 }
148}
149
153void SPFont::update(SPCtx *ctx, guint flags) {
154 if (flags & (SP_OBJECT_MODIFIED_FLAG)) {
161 }
162
163 SPObject::update(ctx, flags);
164}
165
166#define COPY_ATTR(rd,rs,key) (rd)->setAttribute((key), rs->attribute(key));
167
169 if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
170 repr = xml_doc->createElement("svg:font");
171 }
172
173 repr->setAttributeSvgDouble("horiz-origin-x", this->horiz_origin_x);
174 repr->setAttributeSvgDouble("horiz-origin-y", this->horiz_origin_y);
175 repr->setAttributeSvgDouble("horiz-adv-x", this->horiz_adv_x);
176 repr->setAttributeSvgDouble("vert-origin-x", this->vert_origin_x);
177 repr->setAttributeSvgDouble("vert-origin-y", this->vert_origin_y);
178 repr->setAttributeSvgDouble("vert-adv-y", this->vert_adv_y);
179
180 if (repr != this->getRepr()) {
181 // All the below COPY_ATTR functions are directly using
182 // the XML Tree while they shouldn't
183 COPY_ATTR(repr, this->getRepr(), "horiz-origin-x");
184 COPY_ATTR(repr, this->getRepr(), "horiz-origin-y");
185 COPY_ATTR(repr, this->getRepr(), "horiz-adv-x");
186 COPY_ATTR(repr, this->getRepr(), "vert-origin-x");
187 COPY_ATTR(repr, this->getRepr(), "vert-origin-y");
188 COPY_ATTR(repr, this->getRepr(), "vert-adv-y");
189 }
190
191 SPObject::write(xml_doc, repr, flags);
192
193 return repr;
194}
195
197
198SPGlyph* SPFont::create_new_glyph(const char* name, const char* unicode) {
199
201
202 // create a new glyph
203 Inkscape::XML::Node* grepr = xml_doc->createElement("svg:glyph");
204
205 grepr->setAttribute("glyph-name", name);
206 grepr->setAttribute("unicode", unicode);
207
208 // Append the new glyph node to the current font
209 getRepr()->appendChild(grepr);
211
212 // get corresponding object
213 auto g = cast<SPGlyph>(document->getObjectByRepr(grepr));
214
215 g_assert(g != nullptr);
216
217 g->setCollectionPolicy(SPObject::COLLECT_WITH_PARENT);
218
219 return g;
220}
221
223 auto* repr = getRepr();
224 g_assert(repr);
225
226 std::vector<std::pair<SPGlyph*, Node*>> glyphs;
227 glyphs.reserve(repr->childCount());
228
229 // collect all glyphs (SPGlyph and their representations)
230 for (auto&& node : children) {
231 if (auto g = cast<SPGlyph>(&node)) {
232 glyphs.emplace_back(g, g->getRepr());
233 // keep representation around as it gets removed
234 g->getRepr()->anchor();
235 }
236 }
237
238 // now sort by unicode point
239 std::stable_sort(begin(glyphs), end(glyphs), [](const std::pair<SPGlyph*, Node*>& a, const std::pair<SPGlyph*, Node*>& b) {
240 // compare individual unicode points in each string one by one to establish glyph order
241 // note: ustring operator< doesn't work as expected
242 const auto& str1 = a.first->unicode;
243 const auto& str2 = b.first->unicode;
244 return std::lexicographical_compare(str1.begin(), str1.end(), str2.begin(), str2.end());
245 });
246
247 // remove all glyph nodes from the document; block notifications
248 _block = true;
249
250 for (auto&& glyph : glyphs) {
251 repr->removeChild(glyph.second);
252 }
253
254 // re-add them in the desired order
255 for (auto&& glyph : glyphs) {
256 repr->appendChild(glyph.second);
257 glyph.second->release();
258 }
259
260 _block = false;
261 // notify listeners about the change
262 parent->requestModified(SP_OBJECT_MODIFIED_FLAG);
263}
264
265/*
266 Local Variables:
267 mode:c++
268 c-file-style:"stroustrup"
269 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
270 indent-tabs-mode:nil
271 fill-column:99
272 End:
273*/
274// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
Lookup dictionary for attributes/properties.
SPAttr
Definition attributes.h:27
@ VERT_ADV_Y
@ HORIZ_ORIGIN_X
@ VERT_ORIGIN_Y
@ HORIZ_ORIGIN_Y
@ VERT_ORIGIN_X
@ HORIZ_ADV_X
Interface for refcounted XML nodes.
Definition node.h:80
virtual void appendChild(Node *child)=0
Append a node as the last child of this node.
void setAttribute(Util::const_char_ptr key, Util::const_char_ptr value)
Change an attribute of this node.
Definition node.cpp:25
virtual void removeChild(Node *child)=0
Remove a child of this node.
virtual unsigned childCount() const =0
Get the number of children of this node.
bool setAttributeSvgDouble(Util::const_char_ptr key, double val)
For attributes where an exponent is allowed.
Definition node.cpp:111
Typed SVG document implementation.
Definition document.h:101
bool removeResource(char const *key, SPObject *object)
bool addResource(char const *key, SPObject *object)
Inkscape::XML::Document * getReprDoc()
Our Inkscape::XML::Document.
Definition document.h:211
SPObject * getObjectByRepr(Inkscape::XML::Node *repr) const
double horiz_origin_x
Definition sp-font.h:25
bool _block
Definition sp-font.h:52
void child_added(Inkscape::XML::Node *child, Inkscape::XML::Node *ref) override
Callback for child_added event.
Definition sp-font.cpp:59
SPFont()
Definition sp-font.cpp:32
Inkscape::XML::Node * write(Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, unsigned int flags) override
Definition sp-font.cpp:168
double vert_adv_y
Definition sp-font.h:30
SPGlyph * create_new_glyph(const char *name, const char *unicode)
Definition sp-font.cpp:198
void sort_glyphs()
Definition sp-font.cpp:222
double vert_origin_y
Definition sp-font.h:29
void build(SPDocument *doc, Inkscape::XML::Node *repr) override
Definition sp-font.cpp:43
void release() override
Definition sp-font.cpp:75
double horiz_adv_x
Definition sp-font.h:27
void update(SPCtx *ctx, unsigned int flags) override
Receives update notifications.
Definition sp-font.cpp:153
void remove_child(Inkscape::XML::Node *child) override
Callback for remove_child event.
Definition sp-font.cpp:69
~SPFont() override
void set(SPAttr key, char const *value) override
Definition sp-font.cpp:81
double horiz_origin_y
Definition sp-font.h:26
double vert_origin_x
Definition sp-font.h:28
SPObject is an abstract base class of all of the document nodes at the SVG document level.
Definition sp-object.h:160
Inkscape::XML::Node * repr
Definition sp-object.h:193
void requestModified(unsigned int flags)
Requests that a modification notification signal be emitted later (e.g.
SPDocument * document
Definition sp-object.h:188
virtual void set(SPAttr key, const char *value)
virtual void remove_child(Inkscape::XML::Node *child)
virtual Inkscape::XML::Node * write(Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, unsigned int flags)
SPObject * parent
Definition sp-object.h:189
virtual void update(SPCtx *ctx, unsigned int flags)
virtual void release()
@ COLLECT_WITH_PARENT
Definition sp-object.h:164
void readAttr(char const *key)
Read value of key attribute from XML node into object.
Inkscape::XML::Node * getRepr()
Returns the XML representation of tree.
virtual void child_added(Inkscape::XML::Node *child, Inkscape::XML::Node *ref)
virtual void build(SPDocument *doc, Inkscape::XML::Node *repr)
ChildrenList children
Definition sp-object.h:907
Inkscape::XML::Node * node
Geom::Point end
static R & release(R &r)
Decrements the reference count of a anchored object.
static cairo_user_data_key_t key
Ocnode * child[8]
Definition quantize.cpp:33
Ocnode ** ref
Definition quantize.cpp:32
double FNT_DEFAULT_ADV
Definition sp-font.cpp:28
double FNT_DEFAULT_ASCENT
Definition sp-font.cpp:29
double FNT_UNITS_PER_EM
Definition sp-font.cpp:30
Interface for XML documents.
Definition document.h:43
virtual Node * createElement(char const *name)=0
Unused.
Definition sp-object.h:94
Glib::ustring name
Definition toolbars.cpp:55
Interface for XML documents.
Interface for XML nodes.