Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
Layout-TNG-Input.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Inkscape::Text::Layout - text layout engine input functions
4 *
5 * Authors:
6 * Richard Hughes <cyreve@users.sf.net>
7 *
8 * Copyright (C) 2005 Richard Hughes
9 *
10 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
11 */
12
13#ifdef HAVE_CONFIG_H
14# include "config.h" // only include where actually required!
15#endif
16
17#ifndef PANGO_ENABLE_ENGINE
18#define PANGO_ENABLE_ENGINE
19#endif
20
21#include "Layout-TNG.h"
22#include "style.h"
23#include "svg/svg-length.h"
24#include "font-factory.h"
25
26
27namespace Inkscape {
28namespace Text {
29
31{
32 for(auto & it : _input_stream) {
33 delete it;
34 }
35
36 _input_stream.clear();
37 _input_wrap_shapes.clear();
38}
39
40// this function does nothing more than store all its parameters for future reference
41void Layout::appendText(Glib::ustring const &text,
42 SPStyle *style,
43 SPObject *source,
44 OptionalTextTagAttrs const *optional_attributes,
45 unsigned optional_attributes_offset,
46 Glib::ustring::const_iterator text_begin,
47 Glib::ustring::const_iterator text_end)
48{
49 if (style == nullptr) return;
50
52
53 new_source->source = source;
54 new_source->text = &text;
55 new_source->text_begin = text_begin;
56 new_source->text_end = text_end;
57 new_source->style = style;
58 /*
59 * Clear all input sources when any input source's style is deleted.
60 * This is ok, because this is always followed up shortly afterwards
61 * with a full teardown + recreation, so there is no visible effect.
62 */
63 new_source->style_conn = style->object->connectRelease([this] (auto) { clear(); });
64
65 new_source->text_length = 0;
66 for ( ; text_begin != text_end && text_begin != text.end() ; ++text_begin)
67 new_source->text_length++; // save this because calculating the length of a UTF-8 string is expensive
68
69 if (optional_attributes) {
70 // we need to fill in x and y even if the text is empty so that empty paragraphs can be positioned correctly
71 _copyInputVector(optional_attributes->x, optional_attributes_offset, &new_source->x, std::max(1, new_source->text_length));
72 _copyInputVector(optional_attributes->y, optional_attributes_offset, &new_source->y, std::max(1, new_source->text_length));
73 _copyInputVector(optional_attributes->dx, optional_attributes_offset, &new_source->dx, new_source->text_length);
74 _copyInputVector(optional_attributes->dy, optional_attributes_offset, &new_source->dy, new_source->text_length);
75 _copyInputVector(optional_attributes->rotate, optional_attributes_offset, &new_source->rotate, new_source->text_length);
76 if (!optional_attributes->rotate.empty() && optional_attributes_offset >= optional_attributes->rotate.size()) {
77 SVGLength last_rotate;
78 last_rotate = 0.f;
79 for (auto it : optional_attributes->rotate)
80 if (it._set)
81 last_rotate = it;
82 new_source->rotate.resize(1, last_rotate);
83 }
84 new_source->textLength._set = optional_attributes->textLength._set;
85 new_source->textLength.value = optional_attributes->textLength.value;
86 new_source->textLength.computed = optional_attributes->textLength.computed;
87 new_source->textLength.unit = optional_attributes->textLength.unit;
88 new_source->lengthAdjust = optional_attributes->lengthAdjust;
89 }
90
91 _input_stream.push_back(new_source);
92}
93
94void Layout::_copyInputVector(std::vector<SVGLength> const &input_vector, unsigned input_offset, std::vector<SVGLength> *output_vector, size_t max_length)
95{
96 output_vector->clear();
97 if (input_offset >= input_vector.size()) return;
98 output_vector->reserve(std::min(max_length, input_vector.size() - input_offset));
99 while (input_offset < input_vector.size() && max_length != 0) {
100 if (!input_vector[input_offset]._set)
101 break;
102 output_vector->push_back(input_vector[input_offset]);
103 input_offset++;
104 max_length--;
105 }
106}
107
108// just save what we've been given, really
109void Layout::appendControlCode(TextControlCode code, SPObject *source, double width, double ascent, double descent)
110{
112
113 new_code->source = source;
114 new_code->code = code;
115 new_code->width = width;
116 new_code->ascent = ascent;
117 new_code->descent = descent;
118
119 _input_stream.push_back(new_code);
120}
121
122// more saving of the parameters
123void Layout::appendWrapShape(std::unique_ptr<Shape> shape, DisplayAlign display_align)
124{
125 _input_wrap_shapes.push_back({.shape = std::move(shape), .display_align = display_align});
126}
127
129{
130 switch( style->writing_mode.computed ) {
133 return TOP_TO_BOTTOM;
134
136 return RIGHT_TO_LEFT;
137
139 return LEFT_TO_RIGHT;
140
141 default:
142 std::cerr << "Layout::InputTextStream::styleGetBlockProgression: invalid writing mode." << std::endl;
143 }
144 return TOP_TO_BOTTOM;
145}
146
148{
149 return ((SPCSSTextOrientation)style->text_orientation.computed);
150}
151
153{
154 return ((SPCSSBaseline)style->dominant_baseline.computed);
155}
156
157static Layout::Alignment text_anchor_to_alignment(unsigned anchor, Layout::Direction para_direction)
158{
159 switch (anchor) {
160 default:
164 }
165}
166
168{
169 if (!try_text_align)
170 return text_anchor_to_alignment(style->text_anchor.computed, para_direction);
171
172 // there's no way to tell the difference between text-anchor set higher up the cascade to the default and
173 // text-anchor never set anywhere in the cascade, so in order to detect which of text-anchor or text-align
174 // to use we'll have to run up the style tree ourselves.
175 SPStyle const *this_style = style;
176
177 for ( ; ; ) {
178 // If both text-align and text-anchor are set at the same level, text-align takes
179 // precedence because it is the most expressive.
180 if (this_style->text_align.set) {
181 switch (style->text_align.computed) {
182 default:
183 case SP_CSS_TEXT_ALIGN_START: return para_direction == LEFT_TO_RIGHT ? LEFT : RIGHT;
184 case SP_CSS_TEXT_ALIGN_END: return para_direction == LEFT_TO_RIGHT ? RIGHT : LEFT;
185 case SP_CSS_TEXT_ALIGN_LEFT: return LEFT;
186 case SP_CSS_TEXT_ALIGN_RIGHT: return RIGHT;
187 case SP_CSS_TEXT_ALIGN_CENTER: return CENTER;
188 case SP_CSS_TEXT_ALIGN_JUSTIFY: return FULL;
189 }
190 }
191 if (this_style->text_anchor.set)
192 return text_anchor_to_alignment(this_style->text_anchor.computed, para_direction);
193 if (this_style->object == nullptr || this_style->object->parent == nullptr) break;
194 this_style = this_style->object->parent->style;
195 if (this_style == nullptr) break;
196 }
197 return para_direction == LEFT_TO_RIGHT ? LEFT : RIGHT;
198}
199
200std::shared_ptr<FontInstance> Layout::InputStreamTextSource::styleGetFontInstance() const
201{
202 PangoFontDescription *descr = styleGetFontDescription();
203 if (descr == nullptr) return nullptr;
204 auto res = FontFactory::get().Face(descr);
205 pango_font_description_free(descr);
206 return res;
207}
208
210{
211 // This use to be done by code here but it duplicated more complete code in FontFactory.cpp.
213
214 // Font size not yet set
215 // mandatory huge size (hinting workaround)
216 pango_font_description_set_size(descr, FontFactory::get().fontSize * PANGO_SCALE);
217
218 return descr;
219}
220
222
223}//namespace Text
224}//namespace Inkscape
_PangoFontDescription PangoFontDescription
Definition Layout-TNG.h:44
std::shared_ptr< FontInstance > Face(PangoFontDescription *descr, bool canFail=true)
Represents a control code item in the input stream.
Definition Layout-TNG.h:734
Represents a text item in the input stream.
Definition Layout-TNG.h:700
SPCSSTextOrientation styleGetTextOrientation() const
Alignment styleGetAlignment(Direction para_direction, bool try_text_align) const
Glib::ustring::const_iterator text_begin
owned by the caller
Definition Layout-TNG.h:705
std::vector< SVGLength > x
These vectors can (often will) be shorter than the text in this source, but never longer.
Definition Layout-TNG.h:711
PangoFontDescription * styleGetFontDescription() const
The return value must be freed with pango_font_description_free()
Glib::ustring::const_iterator text_end
Definition Layout-TNG.h:705
std::shared_ptr< FontInstance > styleGetFontInstance() const
SPStyle * style
in characters, from text_start to text_end only
Definition Layout-TNG.h:707
void clear()
Empties everything stored in this class and resets it to its original state, like when it was created...
Alignment
For expressing paragraph alignment.
Definition Layout-TNG.h:205
void appendControlCode(TextControlCode code, SPObject *source, double width=0.0, double ascent=0.0, double descent=0.0)
Control codes are metadata in the text stream to signify items that occupy real space (unlike style c...
void _clearInputObjects()
Erases all the stuff set by the owner as input, ie _input_stream and _input_wrap_shapes.
static void _copyInputVector(std::vector< SVGLength > const &input_vector, unsigned input_offset, std::vector< SVGLength > *output_vector, size_t max_length)
The parameters to appendText() are allowed to be a little bit complex.
void appendWrapShape(std::unique_ptr< Shape > shape, DisplayAlign display_align=DISPLAY_ALIGN_BEFORE)
Stores another shape inside which to flow the text.
void appendText(Glib::ustring const &text, SPStyle *style, SPObject *source, OptionalTextTagAttrs const *optional_attributes, unsigned optional_attributes_offset, Glib::ustring::const_iterator text_begin, Glib::ustring::const_iterator text_end)
adds a new piece of text to the end of the current list of text to be processed.
std::vector< InputStreamItem * > _input_stream
This is our internal storage for all the stuff passed to the appendText() and appendControlCode() fun...
Definition Layout-TNG.h:745
DisplayAlign
Display alignment for shapes.
Definition Layout-TNG.h:166
std::vector< InputWrapShape > _input_wrap_shapes
Definition Layout-TNG.h:798
Direction
Used to specify any particular text direction required.
Definition Layout-TNG.h:159
TextControlCode
Control codes which can be embedded in the text to be flowed.
Definition Layout-TNG.h:196
static FontFactory & get(Args &&... args)
Definition statics.h:153
SPObject is an abstract base class of all of the document nodes at the SVG document level.
Definition sp-object.h:160
SPStyle * style
Represents the style properties, whether from presentation attributes, the style attribute,...
Definition sp-object.h:248
sigc::connection connectRelease(sigc::slot< void(SPObject *)> slot)
Connects to the release request signal.
Definition sp-object.h:237
SPObject * parent
Definition sp-object.h:189
An SVG style object.
Definition style.h:45
SPObject * object
Object we are attached to.
Definition style.h:84
T< SPAttr::TEXT_ALIGN, SPIEnum< SPCSSTextAlign > > text_align
text alignment (css2 16.2) (not to be confused with text-anchor)
Definition style.h:150
T< SPAttr::TEXT_ANCHOR, SPIEnum< SPTextAnchor > > text_anchor
Anchor of the text (svg1.1 10.9.1)
Definition style.h:173
T< SPAttr::WRITING_MODE, SPIEnum< SPCSSWritingMode > > writing_mode
Writing mode (svg1.1 10.7.2, CSS Writing Modes 3)
Definition style.h:163
SVG length type.
Definition svg-length.h:22
float value
Definition svg-length.h:47
bool _set
Definition svg-length.h:41
Unit unit
Definition svg-length.h:44
float computed
Definition svg-length.h:50
PangoFontDescription * ink_font_description_from_style(SPStyle const *style)
TODO: insert short description here.
static Layout::Alignment text_anchor_to_alignment(unsigned anchor, Layout::Direction para_direction)
Helper class to stream background task notifications as a series of messages.
The optional attributes which can be applied to a SVG text or related tag.
Definition Layout-TNG.h:184
@ SP_CSS_TEXT_ANCHOR_MIDDLE
@ SP_CSS_TEXT_ANCHOR_START
@ SP_CSS_TEXT_ANCHOR_END
@ SP_CSS_TEXT_ALIGN_END
@ SP_CSS_TEXT_ALIGN_RIGHT
@ SP_CSS_TEXT_ALIGN_CENTER
@ SP_CSS_TEXT_ALIGN_START
@ SP_CSS_TEXT_ALIGN_LEFT
@ SP_CSS_TEXT_ALIGN_JUSTIFY
SPCSSBaseline
@ SP_CSS_WRITING_MODE_TB_RL
@ SP_CSS_WRITING_MODE_LR_TB
@ SP_CSS_WRITING_MODE_TB_LR
@ SP_CSS_WRITING_MODE_RL_TB
SPCSSTextOrientation
SPStyle - a style object for SPItem objects.
double width