Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
Layout-TNG.h
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Inkscape::Text::Layout - text layout engine
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#ifndef SEEN_LAYOUT_TNG_H
13#define SEEN_LAYOUT_TNG_H
14
15//#define DEBUG_TEXTLAYOUT_DUMPASTEXT
16
17#include <2geom/affine.h>
18#include <2geom/d2.h>
19#include <algorithm>
20#include <glibmm/ustring.h>
21#include <memory>
22#include <optional>
23#include <pango/pango-break.h>
24#include <svg/svg-length.h>
25#include <vector>
26
27#include "display/curve.h"
28#include <sigc++/scoped_connection.h>
29#include "livarot/Shape.h"
30#include "style-enums.h"
31
34}
35
37
38class SPStyle;
39class SPObject;
40class Shape;
41struct SPPrintContext;
42class Path;
43class FontInstance;
44using PangoFontDescription = struct _PangoFontDescription;
45
46namespace Inkscape {
47class DrawingGroup;
48
49namespace Text {
50class StyleAttachments;
51
144class Layout {
145public:
146 class iterator;
147 friend class iterator;
148 class Calculator;
149 friend class Calculator;
150 class ScanlineMaker;
152 class ShapeScanlineMaker;
153
155 virtual ~Layout();
156
160
163
164
167
170
171 enum WrapMode {
172 WRAP_NONE, // No wrapping or wrapping via role="line".
173 WRAP_WHITE_SPACE, // Wrapping via 'white-space' property.
174 WRAP_INLINE_SIZE, // Wrapping via 'inline-size' property.
175 WRAP_SHAPE_INSIDE // Wrapping via 'shape-inside' propertry.
177
185 std::vector<SVGLength> x;
186 std::vector<SVGLength> y;
187 std::vector<SVGLength> dx;
188 std::vector<SVGLength> dy;
189 std::vector<SVGLength> rotate;
192 };
193
201
206
209 static const double LINE_HEIGHT_NORMAL;
210
211 // ************************** describing the stuff to flow *************************
212
218
223 void clear();
224
227 bool inputExists() const
228 {return !_input_stream.empty();}
229
230 bool _input_truncated = false;
231 bool inputTruncated() const
232 {return _input_truncated;}
233
258 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);
259 inline void appendText(Glib::ustring const &text, SPStyle *style, SPObject *source, OptionalTextTagAttrs const *optional_attributes = nullptr, unsigned optional_attributes_offset = 0)
260 {appendText(text, style, source, optional_attributes, optional_attributes_offset, text.begin(), text.end());}
261
280 void appendControlCode(TextControlCode code, SPObject *source, double width = 0.0, double ascent = 0.0, double descent = 0.0);
281
294 void appendWrapShape(std::unique_ptr<Shape> shape, DisplayAlign display_align = DISPLAY_ALIGN_BEFORE);
295
296 // ************************** textLength and friends *************************
297
310
313
321
323 double getTextLengthIncrementDue() const;
325 double getTextLengthMultiplierDue() const;
326
330 double getActualLength() const;
331
332 // ************************** doing the actual flowing *************************
333
338
347 bool calculateFlow();
348
350
351 // ************************** operating on the output glyphs *************************
352
358
362 inline bool outputExists() const
363 {return !_characters.empty();}
364
369 void show(DrawingGroup *in_arena, StyleAttachments &style_attachments, Geom::OptRect const &paintbox) const;
370
377 Geom::OptRect bounds(Geom::Affine const &transform, bool with_stroke = false, int start = -1, int length = -1) const;
378
386 void print(SPPrintContext *ctx, Geom::OptRect const &pbox, Geom::OptRect const &dbox, Geom::OptRect const &bbox, Geom::Affine const &ctm) const;
387
391 void showGlyphs(CairoRenderContext *ctx) const;
392
394 Glib::ustring getFontFamily(unsigned span_index) const;
395
396#if DEBUG_TEXTLAYOUT_DUMPASTEXT
400 Glib::ustring dumpAsText() const;
401#endif
402
412 void fitToPathAlign(SVGLength const &startOffset, Path const &path);
413
417 SPCurve convertToCurves(iterator const &from_glyph, iterator const &to_glyph) const;
418 SPCurve convertToCurves() const;
419
423 void transform(Geom::Affine const &transform);
424
426
427 // **********
428
435
438 inline iterator begin() const;
439
442 inline iterator end() const;
443
447 inline iterator charIndexToIterator(int char_index) const;
448
454 inline int iteratorToCharIndex(iterator const &it) const;
455
461 inline void validateIterator(iterator *it) const;
462
465 iterator getNearestCursorPositionTo(double x, double y) const;
466 inline iterator getNearestCursorPositionTo(Geom::Point const &point) const;
467
471 iterator getLetterAt(double x, double y) const;
472 inline iterator getLetterAt(Geom::Point &point) const;
473
474 /* Returns an iterator pointing to the character in the output which
475 was created from the given input. If the character at the given byte
476 offset was removed (soft hyphens, for example) the next character after
477 it is returned. If no input was added with the given object, end() is
478 returned. If more than one input has the same object, the first will
479 be used regardless of the value of \a text_iterator. If
480 \a text_iterator is out of bounds, the first or last character belonging
481 to the given input will be returned accordingly.
482 iterator sourceToIterator(SPObject *source, Glib::ustring::const_iterator text_iterator) const;
483 */
484
489 iterator sourceToIterator(SPObject *source) const;
490
491 // many functions acting on iterators, most of which are obvious
492 // also most of them don't check that \a it != end(). Be careful.
493
497 Geom::OptRect glyphBoundingBox(iterator const &it, double *rotation) const;
498
501 inline unsigned lineIndex(iterator const &it) const;
502
505 inline unsigned shapeIndex(iterator const &it) const;
506
510 inline bool isWhitespace(iterator const &it) const;
511
513 inline gunichar characterAt(iterator const &it) const;
514
516 bool isHidden(iterator const &it) const;
517
525 void getSourceOfCharacter(iterator const &it, SPObject **source, Glib::ustring::iterator *text_iterator = nullptr) const;
526
528 Geom::Point characterAnchorPoint(iterator const &it) const;
529
532 std::optional<Geom::Point> baselineAnchorPoint() const;
533
534 Geom::Path baseline() const;
535
539 std::vector<Geom::LineSegment> getBaselines() const { return _baselines; }
540
543 Geom::Point chunkAnchorPoint(iterator const &it) const;
544
548 Geom::Rect characterBoundingBox(iterator const &it, double *rotation = nullptr) const;
549
554 std::vector<Geom::Point> createSelectionShape(iterator const &it_start, iterator const &it_end, Geom::Affine const &transform) const;
555
558 inline bool isCursorPosition(iterator const &it) const;
559
569 void queryCursorShape(iterator const &it, Geom::Point &position, double &height, double &rotation) const;
570
573 inline bool isStartOfWord(iterator const &it) const;
574
577 inline bool isEndOfWord(iterator const &it) const;
578
581 inline bool isStartOfSentence(iterator const &it) const;
582
585 inline bool isEndOfSentence(iterator const &it) const;
586
589 inline unsigned paragraphIndex(iterator const &it) const;
590
596 inline Alignment paragraphAlignment(iterator const &it) const;
597
605 void simulateLayoutUsingKerning(iterator const &from, iterator const &to, OptionalTextTagAttrs *result) const;
606
608
609
625
626 public:
628
629 void reset() {
630 ascent = 0.8;
631 descent = 0.2;
632 xheight = 0.5;
633 ascent_max = 0.8;
634 descent_max = 0.2;
635 }
636
637 void set(FontInstance const *font);
638
639 // CSS 2.1 dictates that font-size is based on em-size which is defined as ascent + descent
640 inline double emSize() const {return ascent + descent;}
641 // Alternatively name function for use 2.
642 inline double lineSize() const { return ascent + descent; }
643 inline void setZero() {ascent = descent = xheight = ascent_max = descent_max = 0.0;}
644
645 // For scaling for 'font-size'.
646 inline FontMetrics& operator*=(double x) {
647 ascent *= x; descent *= x; xheight *= x; ascent_max *= x; descent_max *= x;
648 return *this;
649 }
650
653 void max(FontMetrics const &other);
654
656 void computeEffective( const double &line_height );
657
658 inline double getTypoAscent() const {return ascent; }
659 inline double getTypoDescent() const {return descent; }
660 inline double getXHeight() const {return xheight; }
661 inline double getMaxAscent() const {return ascent_max; }
662 inline double getMaxDescent() const {return descent_max; }
663
664 // private:
665 double ascent; // Typographic ascent.
666 double descent; // Typographic descent. (Normally positive).
667 double xheight; // Height of 'x' measured from alphabetic baseline.
668 double ascent_max; // Maximum ascent of all glyphs in font.
669 double descent_max; // Maximum descent of all glyphs in font.
670
671 }; // End FontMetrics
672
675
676private:
679 void _clearInputObjects();
680
682 void _clearOutputObjects();
683
685
686 // ******************* input flow
687
688public:
690
692 public:
693 virtual ~InputStreamItem() = default;
694 virtual InputStreamItemType Type() const = 0;
696 };
697
701 public:
702 InputStreamItemType Type() const override {return TEXT_SOURCE;}
704 Glib::ustring const *text;
705 Glib::ustring::const_iterator text_begin, text_end;
708 sigc::scoped_connection style_conn;
711 std::vector<SVGLength> x;
712 std::vector<SVGLength> y;
713 std::vector<SVGLength> dx;
714 std::vector<SVGLength> dy;
715 std::vector<SVGLength> rotate;
718 Glib::ustring lang;
719
720 // a few functions for some of the more complicated style accesses
723 std::shared_ptr<FontInstance> styleGetFontInstance() const;
728 };
729
730private:
735 public:
736 InputStreamItemType Type() const override {return CONTROL_CODE;}
738 double ascent;
739 double descent;
740 double width;
741 };
742
745 std::vector<InputStreamItem*> _input_stream;
746
751 static void _copyInputVector(std::vector<SVGLength> const &input_vector, unsigned input_offset, std::vector<SVGLength> *output_vector, size_t max_length);
752
755 {
756 if(!_input_stream.empty())
757 return static_cast<InputStreamTextSource*>(_input_stream.front())->styleGetBlockProgression();
758 return TOP_TO_BOTTOM;
759 }
760
763 {
764 if(!_input_stream.empty())
765 return static_cast<InputStreamTextSource*>(_input_stream.front())->styleGetTextOrientation();
767 }
768
771 {
772 if(!_input_stream.empty())
773 return static_cast<InputStreamTextSource*>(_input_stream.front())->styleGetDominantBaseline();
775 }
776
779
785
791
792 // ******************* input shapes
793
795 std::unique_ptr<Shape> shape;
797 };
798 std::vector<InputWrapShape> _input_wrap_shapes;
799
800 // ******************* output
801
803 Path const *_path_fitted = nullptr;
804
805public:
806 struct Glyph;
807 struct Character;
808 struct Span;
809 struct Chunk;
810 struct Line;
811 struct Paragraph;
812
813 // A glyph
814 struct Glyph {
815 unsigned int glyph;
816 unsigned in_character;
817 bool hidden;
818 float x;
819 float y;
820 float rotation;
822 float advance;
824 inline std::vector<gunichar> const characters(Layout const *l) const {
825 auto glyph_index = l->_characters[in_character].in_glyph;
826 std::vector<gunichar> ret;
827 for (auto i = in_character; i < l->_characters.size() && l->_characters[i].in_glyph == glyph_index; i++) {
828 ret.push_back(l->_characters[i].the_char);
829 }
830 return ret;
831 }
832 inline Span const & span (Layout const *l) const {return l->_spans[l->_characters[in_character].in_span];}
833 inline Chunk const & chunk(Layout const *l) const {return l->_chunks[l->_spans[l->_characters[in_character].in_span].in_chunk];}
834 inline Line const & line (Layout const *l) const {return l->_lines[l->_chunks[l->_spans[l->_characters[in_character].in_span].in_chunk].in_line];}
835
836 // Get the total transformation for this glyph
837 Geom::Affine transform(Layout const &layout) const;
838 };
839
840 // A unicode character
841 struct Character {
842 unsigned in_span;
843 float x;
847 inline Span const & span (Layout const *l) const {return l->_spans[in_span];}
848 inline Chunk const & chunk (Layout const *l) const {return l->_chunks[l->_spans[in_span].in_chunk];}
849 inline Line const & line (Layout const *l) const {return l->_lines[l->_chunks[l->_spans[in_span].in_chunk].in_line];}
850 inline Paragraph const & paragraph(Layout const *l) const {return l->_paragraphs[l->_lines[l->_chunks[l->_spans[in_span].in_chunk].in_line].in_paragraph];}
851 // to get the advance width of a character, subtract the x values if it's in the middle of a span, or use span.x_end if it's at the end
852 };
853
854 // A collection of characters that share the same style and position start (<text> or <tspan> x, y attributes).
855 struct Span {
856 unsigned in_chunk;
857 std::shared_ptr<FontInstance> font;
859 float x_start;
860 float x_end;
861 float y_offset;
862 inline float width() const {return std::abs(x_start - x_end);}
869 Glib::ustring::const_iterator input_stream_first_character;
870 inline Chunk const & chunk (Layout const *l) const {return l->_chunks[in_chunk]; }
871 inline Line const & line (Layout const *l) const {return l->_lines[l->_chunks[in_chunk].in_line]; }
872 inline Paragraph const & paragraph(Layout const *l) const {return l->_paragraphs[l->_lines[l->_chunks[in_chunk].in_line].in_paragraph];}
873 };
874
875 // A part of a line that is not broken.
876 struct Chunk {
877 unsigned in_line;
878 double left_x;
879 };
880
881 // A line of text. Depending on the shape, it may contain one or more chunks.
882 struct Line {
883 unsigned in_paragraph;
885 unsigned in_shape;
886 bool hidden;
887 };
888
889 // A paragraph. SVG 2 does not contain native paragraphs.
894
898 std::vector<Layout::Glyph> const &glyphs() const { return _glyphs; }
899 std::vector<Layout::Span> const &spans() const { return _spans; }
900 std::vector<InputStreamItem *> const &input_stream() const { return _input_stream; }
901
902private:
903 std::vector<Paragraph> _paragraphs;
904 std::vector<Line> _lines;
905 std::vector<Chunk> _chunks;
906 std::vector<Span> _spans;
907 std::vector<Character> _characters;
908 std::vector<Glyph> _glyphs;
909 std::vector<Geom::LineSegment> _baselines;
910
911 inline unsigned _lineToSpan(unsigned line_index) const
912 {
913 return std::distance(_spans.begin(),
914 std::lower_bound(_spans.begin(), _spans.end(), line_index, [this] (auto &span, unsigned index) {
915 return _chunks[span.in_chunk].in_line < index;
916 })
917 );
918 }
919
920 inline unsigned _lineToCharacter(unsigned line_index) const
921 {
922 return std::distance(_characters.begin(),
923 std::lower_bound(_characters.begin(), _characters.end(), line_index, [this] (auto &character, unsigned index) {
924 return _chunks[_spans[character.in_span].in_chunk].in_line < index;
925 })
926 );
927 }
928
929 inline unsigned _spanToCharacter(unsigned span_index) const
930 {
931 return std::distance(_characters.begin(),
932 std::lower_bound(_characters.begin(), _characters.end(), span_index, [] (auto &character, unsigned index) {
933 return character.in_span < index;
934 })
935 );
936 }
937
938 inline unsigned _sourceToCharacter(unsigned source_index) const
939 {
940 return std::distance(_characters.begin(),
941 std::lower_bound(_characters.begin(), _characters.end(), source_index, [this] (auto &character, unsigned index) {
942 return _spans[character.in_span].in_input_stream_item < index;
943 })
944 );
945 }
946
951 iterator _cursorXOnLineToIterator(unsigned line_index, double local_x, double local_y = 0) const;
952
955 double _getChunkWidth(unsigned chunk_index) const;
956
957 void _calculateBaselines();
958};
959
982public:
983 friend class Layout;
984 // this is just so you can create uninitialised iterators - don't actually try to use one
986 _parent_layout(nullptr),
987 _glyph_index(-1),
988 _char_index(0),
990 _x_coordinate(0.0){}
991 // no copy constructor required, the default does what we want
992 bool operator== (iterator const &other) const
993 {return _glyph_index == other._glyph_index && _char_index == other._char_index;}
994 bool operator!= (iterator const &other) const
995 {return _glyph_index != other._glyph_index || _char_index != other._char_index;}
996
997 /* mustn't compare _glyph_index in these operators because for characters
998 that don't have glyphs (line breaks, elided soft hyphens, etc), the glyph
999 index is -1 which makes them not well-ordered. To be honest, iterating by
1000 glyphs is not very useful and should be avoided. */
1001 bool operator< (iterator const &other) const
1002 {return _char_index < other._char_index;}
1003 bool operator<= (iterator const &other) const
1004 {return _char_index <= other._char_index;}
1005 bool operator> (iterator const &other) const
1006 {return _char_index > other._char_index;}
1007 bool operator>= (iterator const &other) const
1008 {return _char_index >= other._char_index;}
1009
1010 /* **** visual-oriented methods **** */
1011
1012 //glyphs
1013 inline bool prevGlyph();
1014 inline bool nextGlyph();
1015
1016 //span
1020
1021 //chunk
1025
1026 //line
1030 bool thisEndOfLine();
1031
1032 //shape
1036
1037 /* **** text-oriented methods **** */
1038
1039 //characters
1040 inline bool nextCharacter();
1041 inline bool prevCharacter();
1042
1045 bool nextLineCursor(int n = 1);
1046 bool prevLineCursor(int n = 1);
1047
1048 //words
1053
1054 //sentences
1059
1060 //paragraphs
1064 //no endOfPara methods because that's just the previous char
1065
1066 //sources
1070
1071 //logical cursor movement
1072 bool cursorUp(int n = 1);
1073 bool cursorDown(int n = 1);
1074 bool cursorLeft();
1075 bool cursorRight();
1076
1077 //logical cursor movement (by word or paragraph)
1078 bool cursorUpWithControl();
1079 bool cursorDownWithControl();
1080 bool cursorLeftWithControl();
1082
1083private:
1086 unsigned _char_index;
1092
1093 inline iterator(Layout const *p, unsigned c, int g)
1095 inline iterator(Layout const *p, unsigned c)
1097 // no dtor required
1098 void beginCursorUpDown();
1099
1103 bool _cursorLeftOrRightLocalX(Direction direction);
1104
1110};
1111
1112// ************************** inline methods
1113
1115 {return iterator(this, 0, 0);}
1116
1118 {return iterator(this, _characters.size(), _glyphs.size());}
1119
1121{
1122 if (char_index < 0) return begin();
1123 if (char_index >= (int)_characters.size()) return end();
1124 return iterator(this, char_index);
1125}
1126
1128 {return it._char_index;}
1129
1131{
1132 it->_parent_layout = this;
1133 if (it->_char_index >= _characters.size()) {
1134 it->_char_index = _characters.size();
1135 it->_glyph_index = _glyphs.size();
1136 } else
1137 it->_glyph_index = _characters[it->_char_index].in_glyph;
1138}
1139
1141 {return getNearestCursorPositionTo(point[0], point[1]);}
1142
1144 {return getLetterAt(point[0], point[1]);}
1145
1146inline unsigned Layout::lineIndex(iterator const &it) const
1147 {return it._char_index == _characters.size() ? _lines.size() - 1 : _characters[it._char_index].chunk(this).in_line;}
1148
1149inline unsigned Layout::shapeIndex(iterator const &it) const
1150 {return it._char_index == _characters.size() ? _input_wrap_shapes.size() - 1 : _characters[it._char_index].line(this).in_shape;}
1151
1152inline bool Layout::isWhitespace(iterator const &it) const
1153 {return it._char_index == _characters.size() || _characters[it._char_index].char_attributes.is_white;}
1154
1156{
1157 return _characters[it._char_index].the_char;
1158}
1159
1160inline bool Layout::isCursorPosition(iterator const &it) const
1161 {return it._char_index == _characters.size() || _characters[it._char_index].char_attributes.is_cursor_position;}
1162
1163inline bool Layout::isStartOfWord(iterator const &it) const
1164 {return it._char_index != _characters.size() && _characters[it._char_index].char_attributes.is_word_start;}
1165
1166inline bool Layout::isEndOfWord(iterator const &it) const
1167 {return it._char_index == _characters.size() || _characters[it._char_index].char_attributes.is_word_end;}
1168
1169inline bool Layout::isStartOfSentence(iterator const &it) const
1170 {return it._char_index != _characters.size() && _characters[it._char_index].char_attributes.is_sentence_start;}
1171
1172inline bool Layout::isEndOfSentence(iterator const &it) const
1173 {return it._char_index == _characters.size() || _characters[it._char_index].char_attributes.is_sentence_end;}
1174
1175inline unsigned Layout::paragraphIndex(iterator const &it) const
1176 {return it._char_index == _characters.size() ? _paragraphs.size() - 1 : _characters[it._char_index].line(this).in_paragraph;}
1177
1179 {return (_paragraphs.size() == 0) ? NONE : _paragraphs[paragraphIndex(it)].alignment;}
1180
1182{
1184 if (_glyph_index >= (int)_parent_layout->_glyphs.size() - 1) {
1185 if (_glyph_index == (int)_parent_layout->_glyphs.size()) return false;
1188 }
1189 else _char_index = _parent_layout->_glyphs[++_glyph_index].in_character;
1190 return true;
1191}
1192
1194{
1195 _cursor_moving_vertically = false;
1196 if (_glyph_index == 0) return false;
1197 _char_index = _parent_layout->_glyphs[--_glyph_index].in_character;
1198 return true;
1199}
1200
1202{
1203 _cursor_moving_vertically = false;
1204 if (_char_index + 1 >= _parent_layout->_characters.size()) {
1205 if (_char_index == _parent_layout->_characters.size()) return false;
1206 _char_index = _parent_layout->_characters.size();
1207 _glyph_index = _parent_layout->_glyphs.size();
1208 }
1209 else _glyph_index = _parent_layout->_characters[++_char_index].in_glyph;
1210 return true;
1211}
1212
1214{
1215 _cursor_moving_vertically = false;
1216 if (_char_index == 0) return false;
1217 _glyph_index = _parent_layout->_characters[--_char_index].in_glyph;
1218 return true;
1219}
1220
1221}//namespace Text
1222}//namespace Inkscape
1223
1224std::ostream &operator<<(std::ostream &out, const Inkscape::Text::Layout::FontMetrics &f);
1225std::ostream &operator<<(std::ostream &out, const Inkscape::Text::Layout::FontMetrics *f);
1226
1227
1228#endif
1229
1230
1231/*
1232 Local Variables:
1233 mode:c++
1234 c-file-style:"stroustrup"
1235 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
1236 indent-tabs-mode:nil
1237 fill-column:99
1238 End:
1239*/
1240// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
_PangoFontDescription PangoFontDescription
Definition Layout-TNG.h:44
TODO: insert short description here.
3x3 affine transformation matrix.
Geom::IntRect bounds
Definition canvas.cpp:182
FontInstance provides metrics, OpenType data, and glyph curves/pixbufs for a font.
3x3 matrix representing an affine transformation.
Definition affine.h:70
Axis-aligned rectangle that can be empty.
Definition rect.h:203
Sequence of contiguous curves, aka spline.
Definition path.h:353
Two-dimensional point that doubles as a vector.
Definition point.h:66
Axis aligned, non-empty rectangle.
Definition rect.h:92
Keep track of font metrics.
Definition Layout-TNG.h:624
FontMetrics & operator*=(double x)
Definition Layout-TNG.h:646
void computeEffective(const double &line_height)
Calculate the effective ascent and descent including half "leading".
Represents a control code item in the input stream.
Definition Layout-TNG.h:734
InputStreamItemType Type() const override
Definition Layout-TNG.h:736
virtual InputStreamItemType Type() const =0
Represents a text item in the input stream.
Definition Layout-TNG.h:700
InputStreamItemType Type() const override
Definition Layout-TNG.h:702
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
Holds a position within the glyph output of Layout.
Definition Layout-TNG.h:981
iterator(Layout const *p, unsigned c, int g)
bool operator!=(iterator const &other) const
Definition Layout-TNG.h:994
bool _cursorLeftOrRightLocalX(Direction direction)
stores the current x coordinate so that the cursor won't drift. See _x_coordinate
bool operator<(iterator const &other) const
bool _cursor_moving_vertically
index into Layout::character
unsigned _char_index
index into Layout::glyphs, or -1
bool operator>=(iterator const &other) const
iterator(Layout const *p, unsigned c)
bool operator>(iterator const &other) const
bool operator<=(iterator const &other) const
double _x_coordinate
for cursor up/down movement we must maintain the x position where we started so the cursor doesn't 'd...
bool _cursorLeftOrRightLocalXByWord(Direction direction)
moves forward or backwards by until the next character with is_word_start according to the directiona...
Generates the layout for either wrapped or non-wrapped text and stores the result.
Definition Layout-TNG.h:144
iterator getLetterAt(double x, double y) const
Returns an iterator pointing to the letter whose bounding box contains the given coordinates.
void transform(Geom::Affine const &transform)
Apply the given transform to all the output presently stored in this object.
std::vector< Geom::Point > createSelectionShape(iterator const &it_start, iterator const &it_end, Geom::Affine const &transform) const
Basically uses characterBoundingBox() on all the characters from start to end and returns the union o...
void clear()
Empties everything stored in this class and resets it to its original state, like when it was created...
SPCSSBaseline _blockBaseline() const
The overall text-orientation of the whole flow.
Definition Layout-TNG.h:770
void simulateLayoutUsingKerning(iterator const &from, iterator const &to, OptionalTextTagAttrs *result) const
Returns kerning information which could cause the current output to be exactly reproduced if the lett...
unsigned _spanToCharacter(unsigned span_index) const
Definition Layout-TNG.h:929
LengthAdjust lengthAdjust
How do we meet textLength if specified: by letterspacing or by scaling horizontally.
Definition Layout-TNG.h:312
SPCSSTextOrientation _blockTextOrientation() const
The overall text-orientation of the whole flow.
Definition Layout-TNG.h:762
std::vector< Geom::LineSegment > getBaselines() const
Returns all the baselines of a text element.
Definition Layout-TNG.h:539
std::vector< Line > _lines
Definition Layout-TNG.h:904
iterator charIndexToIterator(int char_index) const
Returns an iterator pointing at the given character index.
void queryCursorShape(iterator const &it, Geom::Point &position, double &height, double &rotation) const
Gets the ideal cursor shape for a given iterator.
std::vector< Layout::Glyph > const & glyphs() const
Publically allow access to the Layout::show logic outside of the Layout engine.
Definition Layout-TNG.h:898
bool inputTruncated() const
Definition Layout-TNG.h:231
unsigned shapeIndex(iterator const &it) const
Returns the zero-based number of the shape which contains the character pointed to by it.
Alignment
For expressing paragraph alignment.
Definition Layout-TNG.h:205
double getTextLengthMultiplierDue() const
Get the actual scale multiplier if it's due with the current values of above stuff,...
unsigned lineIndex(iterator const &it) const
Returns the zero-based line number of the character pointed to by it.
void validateIterator(iterator *it) const
Checks the validity of the given iterator over the current layout.
static const double LINE_HEIGHT_NORMAL
The CSS spec allows line-height:normal to be whatever the user agent thinks will look good.
Definition Layout-TNG.h:209
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...
std::vector< Glyph > _glyphs
Definition Layout-TNG.h:908
iterator sourceToIterator(SPObject *source) const
Returns an iterator pointing to the first character in the output which was created from the given so...
bool inputExists() const
Queries whether any calls have been made to appendText() or appendControlCode() since the object was ...
Definition Layout-TNG.h:227
bool isCursorPosition(iterator const &it) const
Returns true if it points to a character which is a valid cursor position, as defined by Pango.
void _clearInputObjects()
Erases all the stuff set by the owner as input, ie _input_stream and _input_wrap_shapes.
bool isHidden(iterator const &it) const
Returns true if the text at it is hidden (i.e.
unsigned _lineToSpan(unsigned line_index) const
Definition Layout-TNG.h:911
std::vector< Chunk > _chunks
Definition Layout-TNG.h:905
void appendText(Glib::ustring const &text, SPStyle *style, SPObject *source, OptionalTextTagAttrs const *optional_attributes=nullptr, unsigned optional_attributes_offset=0)
Definition Layout-TNG.h:259
Geom::Point characterAnchorPoint(iterator const &it) const
For latin text, the left side of the character, on the baseline.
iterator _cursorXOnLineToIterator(unsigned line_index, double local_x, double local_y=0) const
given an x and y coordinate and a line number, returns an iterator pointing to the closest cursor pos...
void _clearOutputObjects()
Erases all the stuff output by computeFlow().
std::vector< Geom::LineSegment > _baselines
Definition Layout-TNG.h:909
Direction _blockProgression() const
The overall block-progression of the whole flow.
Definition Layout-TNG.h:754
struct Inkscape::Text::Layout::CursorShape _empty_cursor_shape
bool isEndOfWord(iterator const &it) const
Returns true if it points to a character which is a the end of a word, as defined by Pango.
double textLengthIncrement
This one is used by letterspacing strategy: to each glyph width, this is added.
Definition Layout-TNG.h:320
Glib::ustring dumpAsText() const
debug and unit test method.
std::optional< Geom::Point > baselineAnchorPoint() const
For left aligned text, the leftmost end of the baseline For rightmost text, the rightmost....
void show(DrawingGroup *in_arena, StyleAttachments &style_attachments, Geom::OptRect const &paintbox) const
Adds all the output glyphs to in_arena using the given paintbox.
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.
Glib::ustring getFontFamily(unsigned span_index) const
Returns the font family of the indexed span.
void fitToPathAlign(SVGLength const &startOffset, Path const &path)
Moves all the glyphs in the structure so that the baseline of all the characters sits neatly along th...
unsigned _sourceToCharacter(unsigned source_index) const
Definition Layout-TNG.h:938
gunichar characterAt(iterator const &it) const
Returns character pointed to by it.
Geom::Point chunkAnchorPoint(iterator const &it) const
This is that value to apply to the x,y attributes of tspan role=line elements, and hence it takes ali...
std::vector< InputStreamItem * > const & input_stream() const
Definition Layout-TNG.h:900
std::vector< Paragraph > _paragraphs
Definition Layout-TNG.h:903
void _calculateCursorShapeForEmpty()
If the output is empty callers still want to be able to call queryCursorShape() and get a valid answe...
static bool _directions_are_orthogonal(Direction d1, Direction d2)
so that LEFT_TO_RIGHT == RIGHT_TO_LEFT but != TOP_TO_BOTTOM
int iteratorToCharIndex(iterator const &it) const
Returns the character index from the start of the flow represented by the given iterator.
bool isEndOfSentence(iterator const &it) const
Returns true if it points to a character which is a the end of a sentence, as defined by Pango.
iterator end() const
Returns an iterator pointing just past the end of the last glyph, which is also just past the end of ...
Geom::Rect characterBoundingBox(iterator const &it, double *rotation=nullptr) const
Returns the box extents (not ink extents) of the given character.
double textLengthMultiplier
By how much each character needs to be wider or narrower, using the specified lengthAdjust strategy,...
Definition Layout-TNG.h:318
double getActualLength() const
Get actual length of layout, by summing span lengths.
void appendWrapShape(std::unique_ptr< Shape > shape, DisplayAlign display_align=DISPLAY_ALIGN_BEFORE)
Stores another shape inside which to flow the text.
void getSourceOfCharacter(iterator const &it, SPObject **source, Glib::ustring::iterator *text_iterator=nullptr) const
Discovers where the character pointed to by it came from, by retrieving the object that was passed to...
bool isStartOfSentence(iterator const &it) const
Returns true if it points to a character which is a the start of a sentence, as defined by Pango.
Alignment paragraphAlignment(iterator const &it) const
Returns the actual alignment used for the paragraph containing the character pointed to by it.
unsigned paragraphIndex(iterator const &it) const
Returns the zero-based number of the paragraph containing the character pointed to by it.
double getTextLengthIncrementDue() const
Get the actual spacing increment if it's due with the current values of above stuff,...
enum Inkscape::Text::Layout::WrapMode wrap_mode
bool outputExists() const
Returns true if there are some glyphs in this object, ie whether computeFlow() has been called on a n...
Definition Layout-TNG.h:362
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.
friend class Calculator
Definition Layout-TNG.h:149
bool isWhitespace(iterator const &it) const
Returns true if the character at it is a whitespace, as defined by Pango.
FontMetrics strut
The strut is the minimum value used in calculating line height.
Definition Layout-TNG.h:674
SVGLength textLength
Gives the length target of this layout, as given by textLength attribute.
Definition Layout-TNG.h:309
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
void print(SPPrintContext *ctx, Geom::OptRect const &pbox, Geom::OptRect const &dbox, Geom::OptRect const &bbox, Geom::Affine const &ctm) const
Sends all the glyphs to the given print context.
unsigned _lineToCharacter(unsigned line_index) const
Definition Layout-TNG.h:920
double _getChunkWidth(unsigned chunk_index) const
calculates the width of a chunk, which is the largest x coordinate (start or end) of the spans contai...
std::vector< Character > _characters
Definition Layout-TNG.h:907
DisplayAlign
Display alignment for shapes.
Definition Layout-TNG.h:166
std::vector< InputWrapShape > _input_wrap_shapes
Definition Layout-TNG.h:798
void showGlyphs(CairoRenderContext *ctx) const
Renders all the glyphs to the given Cairo rendering context.
Geom::OptRect glyphBoundingBox(iterator const &it, double *rotation) const
Returns the bounding box of the given glyph, and its rotation.
bool calculateFlow()
Takes all the stuff you set with the members above here and creates a load of glyphs for use with the...
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
@ ARBITRARY_GAP
forces the flow to ignore the remainder of the current shape (from #flow_inside_shapes) and continue ...
Definition Layout-TNG.h:199
@ SHAPE_BREAK
forces the flow to move on to the next line
Definition Layout-TNG.h:198
Orientation
Used to specify orientation of glyphs in vertical text.
Definition Layout-TNG.h:162
Path const * _path_fitted
as passed to fitToPathAlign()
Definition Layout-TNG.h:803
LengthAdjust
lengthAdjust values
Definition Layout-TNG.h:169
static const gunichar UNICODE_SOFT_HYPHEN
Definition Layout-TNG.h:684
iterator getNearestCursorPositionTo(double x, double y) const
Returns an iterator pointing to the cursor position for a mouse click at the given coordinates.
std::vector< Layout::Span > const & spans() const
Definition Layout-TNG.h:899
bool isStartOfWord(iterator const &it) const
Returns true if it points to a character which is a the start of a word, as defined by Pango.
iterator begin() const
Returns an iterator pointing at the first glyph of the flowed output.
std::vector< Span > _spans
Definition Layout-TNG.h:906
Path and its polyline approximation.
Definition Path.h:93
Wrapper around a Geom::PathVector object.
Definition curve.h:28
SPObject is an abstract base class of all of the document nodes at the SVG document level.
Definition sp-object.h:160
An SVG style object.
Definition style.h:45
SVG length type.
Definition svg-length.h:22
A class to store/manipulate directed graphs.
Definition Shape.h:65
Css & result
double c[8][4]
Lifts one dimensional objects into 2D.
Geom::Point start
Helper class to stream background task notifications as a series of messages.
Chunk const & chunk(Layout const *l) const
Definition Layout-TNG.h:848
PangoLogAttr char_attributes
relative to the start of the span (so we can do block-progression)
Definition Layout-TNG.h:844
Line const & line(Layout const *l) const
Definition Layout-TNG.h:849
Paragraph const & paragraph(Layout const *l) const
Definition Layout-TNG.h:850
Span const & span(Layout const *l) const
will be -1 if this character has no visual representation
Definition Layout-TNG.h:847
std::vector< gunichar > const characters(Layout const *l) const
to implement lengthAdjust="spacingAndGlyphs" that must scale glyphs only horizontally; instead we cha...
Definition Layout-TNG.h:824
float vertical_scale
for positioning next glyph
Definition Layout-TNG.h:823
Line const & line(Layout const *l) const
Definition Layout-TNG.h:834
float advance
Orientation of glyph in vertical text.
Definition Layout-TNG.h:822
float y
relative to the start of the chunk
Definition Layout-TNG.h:819
Span const & span(Layout const *l) const
Definition Layout-TNG.h:832
Geom::Affine transform(Layout const &layout) const
Chunk const & chunk(Layout const *l) const
Definition Layout-TNG.h:833
float rotation
relative to the current line's baseline
Definition Layout-TNG.h:820
Orientation orientation
absolute, modulo any object transforms, which we don't know about
Definition Layout-TNG.h:821
DisplayAlign display_align
as passed to Layout::appendWrapShape()
Definition Layout-TNG.h:796
std::unique_ptr< Shape > shape
as passed to Layout::appendWrapShape()
Definition Layout-TNG.h:795
The optional attributes which can be applied to a SVG text or related tag.
Definition Layout-TNG.h:184
Alignment alignment
can be overridden by child Span objects
Definition Layout-TNG.h:892
unsigned in_input_stream_item
See CSS3 section 3.2. The direction in which lines go.
Definition Layout-TNG.h:868
Chunk const & chunk(Layout const *l) const
Definition Layout-TNG.h:870
float y_offset
relative to the start of the chunk
Definition Layout-TNG.h:861
float width() const
relative to line baseline (without baseline shift)
Definition Layout-TNG.h:862
std::shared_ptr< FontInstance > font
Definition Layout-TNG.h:857
Glib::ustring::const_iterator input_stream_first_character
Definition Layout-TNG.h:869
Direction block_progression
See CSS3 section 3.2. Either rtl or ltr.
Definition Layout-TNG.h:867
float x_end
relative to the start of the chunk
Definition Layout-TNG.h:860
Paragraph const & paragraph(Layout const *l) const
Definition Layout-TNG.h:872
Line const & line(Layout const *l) const
Definition Layout-TNG.h:871
SPCSSTextOrientation text_orientation
relative to the line's baseline (CSS)
Definition Layout-TNG.h:865
SPStyle enums: named public enums that correspond to SVG property values.
SPCSSBaseline
@ SP_CSS_BASELINE_AUTO
SPCSSTextOrientation
@ SP_CSS_TEXT_ORIENTATION_MIXED
int index
double height
double width
unsigned int gunichar