Code

Updating the READMEs to better handle OSX.
[inkscape.git] / src / libnrtype / Layout-TNG.h
1 /*
2  * Inkscape::Text::Layout - text layout engine
3  *
4  * Authors:
5  *   Richard Hughes <cyreve@users.sf.net>
6  *
7  * Copyright (C) 2005 Richard Hughes
8  *
9  * Released under GNU GPL, read the file 'COPYING' for more information
10  */
11 #ifndef __LAYOUT_TNG_H__
12 #define __LAYOUT_TNG_H__
14 #ifdef HAVE_CONFIG_H
15 # include "config.h"
16 #endif
17 #include <libnr/nr-matrix-ops.h>
18 #include <libnr/nr-rotate-ops.h>
19 #include <libnr/nr-rect.h>
20 #include <2geom/d2.h>
21 #include <2geom/matrix.h>
22 #include <glibmm/ustring.h>
23 #include <pango/pango-break.h>
24 #include <algorithm>
25 #include <vector>
26 #include <boost/optional.hpp>
28 #ifdef HAVE_CAIRO_PDF
29 namespace Inkscape {
30         namespace Extension {
31                 namespace Internal {
32                         class CairoRenderContext;
33                 }
34         }
35 }
37 using Inkscape::Extension::Internal::CairoRenderContext;
38 #endif
40 class SPStyle;
41 class Shape;
42 class NRArenaGroup;
43 class SPPrintContext;
44 class SVGLength;
45 class Path;
46 class SPCurve;
47 class font_instance;
48 typedef struct _PangoFontDescription PangoFontDescription;
50 namespace Inkscape {
51 namespace Text {
53 /** \brief Generates the layout for either wrapped or non-wrapped text and stores the result
55 Use this class for all your text output needs. It takes text with formatting
56 markup as input and turns that into the glyphs and their necessary positions.
57 It stores the glyphs internally, but maintains enough information to both
58 retrieve your own rendering information if you wish and to perform visual
59 text editing where the output refers back to where it came from.
61 Usage:
62 -# Construct
63 -# Set the text using appendText() and appendControlCode()
64 -# If you want text wrapping, call appendWrapShape() a few times
65 -# Call calculateFlow()
66 -# You can go several directions from here, but the most interesting
67    things start with creating a Layout::iterator with begin() or end().
69 Terminology, in descending order of size:
70 - Flow: Not often used, but when it is it means all the text
71 - Shape: A Shape object which is used to represent one of the regions inside
72   which to flow the text. Can overlap with...
73 - Paragraph: Err...A paragraph. Contains one or more...
74 - Line: An entire horizontal line with a common baseline. Contains one or
75   more...
76 - Chunk: You only get more than one of these when a shape is sufficiently
77   complex that the text has to flow either side of some obstruction in
78   the middle. A chunk is the base unit for wrapping. Contains one or more...
79 - Span: A convenient subset of a chunk with the same font, style,
80   directionality, block progression and input stream. Fill and outline
81   need not be constant because that's a later rendering stage.
82 - This is where it gets weird because a span will contain one or more 
83   elements of both of the following, which can overlap with each other in
84   any way:
85   - Character: a single Unicode codepoint from an input stream. Many arabic
86     characters contain multiple glyphs
87   - Glyph: a rendering primitive for font engines. A ligature glyph will
88     represent multiple characters.
90 Other terminology:
91 - Input stream: An object representing a single call to appendText() or
92   appendControlCode().
93 - Control code: Metadata in the text stream to signify items that occupy
94   real space (unlike style changes) but don't belong in the text string.
95   Paragraph breaks are in this category. See Layout::TextControlCode.
96 - SVG1.1: The W3C Recommendation "Scalable Vector Graphics (SVG) 1.1"
97   http://www.w3.org/TR/SVG11/
98 - 'left', 'down', etc: These terms are generally used to mean what they
99   mean in left-to-right, top-to-bottom text but rotated or reflected for
100   the current directionality. Thus, the 'width' of a ttb line is actually
101   its height, and the (internally stored) y coordinate of a glyph is
102   actually its x coordinate. Confusing to the reader but much simpler in
103   the code. All public methods use real x and y.
105 Comments:
106 - There's a strong emphasis on international support in this class, but
107   that's primarily because once you can display all the insane things
108   required by various languages, simple things like styling text are
109   almost trivial.
110 - There are a few places (appendText() is one) where pointers are held to
111   caller-owned objects and used for quite a long time. This is messy but
112   is safe for our usage scenario and in many cases the cost of copying the
113   objects is quite high.
114 - "Why isn't foo here?": Ask yourself if it's possible to implement foo
115   externally using iterators. However this may not mean that it doesn't
116   belong as a member, though.
117 - I've used floats rather than doubles to store relative distances in some
118   places (internal only) where it would save significant amounts of memory.
119   The SVG spec allows you to do this as long as intermediate calculations
120   are done double. Very very long lines might not finish precisely where
121   you want, but that's to be expected with any typesetting. Also,
122   SVGLength only uses floats.
123 - If you look at the six arrays for holding the output data you'll realise
124   that there's no O(1) way to drill down from a paragraph to find its
125   starting glyph. This was a conscious decision to reduce complexity and
126   to save memory. Drilling down isn't actually that slow because a binary
127   chop will work nicely. Add this to the realisation that most of the
128   times you do this will be in response to user actions and hence you only
129   need to be faster than the user and I think the design makes sense.
130 - There are a massive number of functions acting on Layout::iterator. A
131   large number are trivial and will be inline, but is it really necessary
132   to have all these, especially when some can be implemented by the caller
133   using the others?
134 - The separation of methods between Layout and Layout::iterator is a
135   bit arbitrary, because many methods could go in either. I've used the STL
136   model where the iterator itself can only move around; the base class is
137   required to do anything interesting.
138 - I use Pango internally, not Pangomm. The reason for this is lots of
139   Pangomm methods take Glib::ustrings as input and then output byte offsets
140   within the strings. There's simply no way to use byte offsets with
141   ustrings without some very entertaining reinterpret_cast<>s. The Pangomm
142   docs seem to be lacking quite a lot of things mentioned in the Pango
143   docs, too.
144 */
145 class Layout {
146 public:
147     class iterator;
148     friend class iterator;
149     class Calculator;
150     friend class Calculator;
151     class ScanlineMaker;
152     class InfiniteScanlineMaker;
153     class ShapeScanlineMaker;
155     Layout();
156     virtual ~Layout();
158     /** Used to specify any particular text direction required. Used for
159     both the 'direction' and 'block-progression' CSS attributes. */
160     enum Direction {LEFT_TO_RIGHT, RIGHT_TO_LEFT, TOP_TO_BOTTOM, BOTTOM_TO_TOP};
162     /** Display alignment for shapes. See appendWrapShape(). */
163     enum DisplayAlign {DISPLAY_ALIGN_BEFORE, DISPLAY_ALIGN_CENTER, DISPLAY_ALIGN_AFTER};
165     /** The optional attributes which can be applied to a SVG text or
166     related tag. See appendText(). See SVG1.1 section 10.4 for the
167     definitions of all these members. See sp_svg_length_list_read() for
168     the standard way to make these vectors. It is the responsibility of
169     the caller to deal with the inheritance of these values using its
170     knowledge of the parse tree. */
171     struct OptionalTextTagAttrs {
172         std::vector<SVGLength> x;
173         std::vector<SVGLength> y;
174         std::vector<SVGLength> dx;
175         std::vector<SVGLength> dy;
176         std::vector<SVGLength> rotate;
177     };
179     /** Control codes which can be embedded in the text to be flowed. See
180     appendControlCode(). */
181     enum TextControlCode {
182         PARAGRAPH_BREAK,    /// forces the flow to move on to the next line
183         SHAPE_BREAK,        /// forces the flow to ignore the remainder of the current shape (from #flow_inside_shapes) and continue at the top of the one after.
184         ARBITRARY_GAP       /// inserts an arbitrarily-sized hole in the flow in line with the current text.
185     };
187     /** For expressing paragraph alignment. These values are rotated in the
188     case of vertical text, but are not dependent on whether the paragraph is
189     rtl or ltr, thus LEFT is always either left or top. */
190     enum Alignment {LEFT, CENTER, RIGHT, FULL};
192     /** The CSS spec allows line-height:normal to be whatever the user agent
193     thinks will look good. This is our value, as a multiple of font-size. */
194     static const double LINE_HEIGHT_NORMAL;
196     // ************************** describing the stuff to flow *************************
198     /** \name Input
199       Methods for describing the text you want to flow, its style, and the
200       shapes to flow in to.
201     */
202     //@{
204     /** Empties everything stored in this class and resets it to its
205     original state, like when it was created. All iterators on this
206     object will be invalidated (but can be revalidated using
207     validateIterator(). */
208     void clear();
210     /** Queries whether any calls have been made to appendText() or
211     appendControlCode() since the object was last cleared. */
212     bool inputExists() const
213         {return !_input_stream.empty();}
215     bool inputTruncated() const;
217     /** adds a new piece of text to the end of the current list of text to
218     be processed. This method can only add text of a consistent style.
219     To add lots of different styles, call it lots of times.
220      \param text  The text. \b Note: only a \em pointer is stored. Do not
221                   mess with the text until after you have called
222                   calculateFlow().
223      \param style The font style. Layout will hold a reference to this
224                   object for the duration of its ownership, ie until you
225                   call clear() or the class is destroyed. Must not be NULL.
226      \param source_cookie  This pointer is treated as opaque by Layout
227                   but will be passed through the flowing process intact so
228                   that callers can use it to refer to the original object
229                   that generated a particular glyph. See Layout::iterator.
230                   Implementation detail: currently all callers put an
231                   SPString in here.
232      \param optional_attributes  A structure containing additional options
233                   for this text. See OptionalTextTagAttrs. The values are
234                   copied to internal storage before this method returns.
235      \param optional_attributes_offset  It is convenient for callers to be
236                   able to use the same \a optional_attributes structure for
237                   several sequential text fields, in which case the vectors
238                   will need to be offset. This parameter causes the <i>n</i>th
239                   element of all the vectors to be read as if it were the
240                   first.
241      \param text_begin  Used for selecting only a substring of \a text
242                   to process.
243      \param text_end    Used for selecting only a substring of \a text
244                   to process.
245     */
246     void appendText(Glib::ustring const &text, SPStyle *style, void *source_cookie, OptionalTextTagAttrs const *optional_attributes, unsigned optional_attributes_offset, Glib::ustring::const_iterator text_begin, Glib::ustring::const_iterator text_end);
247     inline void appendText(Glib::ustring const &text, SPStyle *style, void *source_cookie, OptionalTextTagAttrs const *optional_attributes = NULL, unsigned optional_attributes_offset = 0)
248         {appendText(text, style, source_cookie, optional_attributes, optional_attributes_offset, text.begin(), text.end());}
250     /** Control codes are metadata in the text stream to signify items
251     that occupy real space (unlike style changes) but don't belong in the
252     text string. See TextControlCode for the types available.
254     A control code \em cannot be the first item in the input stream. Use
255     appendText() with an empty string to set up the paragraph properties.
256      \param code    A member of the TextFlowControlCode enumeration.
257      \param width   The width in pixels that this item occupies.
258      \param ascent  The number of pixels above the text baseline that this
259                     control code occupies.
260      \param descent The number of pixels below the text baseline that this
261                     control code occupies.
262      \param source_cookie This pointer is treated as opaque by Layout
263                   but will be passed through the flowing process intact so
264                   that callers can use it to refer to the original object
265                   that generated a particular area. See Layout::iterator.
266                   Implementation detail: currently all callers put an
267                   SPObject in here.
268     Note that for some control codes (eg tab) the values of the \a width,
269     \a ascender and \a descender are implied by the surrounding text (and
270     in the case of tabs, the values set in tab_stops) so the values you pass
271     here are ignored.
272     */
273     void appendControlCode(TextControlCode code, void *source_cookie, double width = 0.0, double ascent = 0.0, double descent = 0.0);
275     /** Stores another shape inside which to flow the text. If this method
276     is never called then no automatic wrapping is done and lines will
277     continue to infinity if necessary. Text can be flowed inside multiple
278     shapes in sequence, like with frames in a DTP package. If the text flows
279     past the end of the last shape all remaining text is ignored.
281       \param shape  The Shape to use next in the flow. The storage for this
282                     is managed by the caller, and need only be valid for
283                     the duration of the call to calculateFlow().
284       \param display_align   The vertical alignment of the text within this
285                     shape. See XSL1.0 section 7.13.4. The behaviour of
286                     settings other than DISPLAY_ALIGN_BEFORE when using
287                     non-rectangular shapes is undefined.
288     */
289     void appendWrapShape(Shape const *shape, DisplayAlign display_align = DISPLAY_ALIGN_BEFORE);
291     //@}
293     // ************************** doing the actual flowing *************************
295     /** \name Processing
296       The method to do the actual work of converting text into glyphs.
297     */
298     //@{
300     /** Takes all the stuff you set with the members above here and creates
301     a load of glyphs for use with the members below here. All iterators on
302     this object will be invalidated (but can be fixed with validateIterator().
303     The implementation just creates a new Layout::Calculator and calls its
304     Calculator::Calculate() method, so if you want more details on the
305     internals, go there.
306       \return  false on failure.
307     */
308     bool calculateFlow();
310     //@}
312     // ************************** operating on the output glyphs *************************
314     /** \name Output
315       Methods for reading and interpreting the output glyphs. See also
316       Layout::iterator.
317     */
318     //@{
320     /** Returns true if there are some glyphs in this object, ie whether
321     computeFlow() has been called on a non-empty input since the object was
322     created or the last call to clear(). */
323     inline bool outputExists() const
324         {return !_characters.empty();}
326     /** Adds all the output glyphs to \a in_arena using the given \a paintbox.
327      \param in_arena  The arena to add the glyphs group to
328      \param paintbox  The current rendering tile
329     */
330     void show(NRArenaGroup *in_arena, NRRect const *paintbox) const;
332     /** Calculates the smallest rectangle completely enclosing all the
333     glyphs.
334       \param bounding_box  Where to store the box
335       \param transform     The transform to be applied to the entire object
336                            prior to calculating its bounds.
337     */
338     void getBoundingBox(NRRect *bounding_box, Geom::Matrix const &transform, int start = -1, int length = -1) const;
340     /** Sends all the glyphs to the given print context.
341      \param ctx   I have
342      \param pbox  no idea
343      \param dbox  what these
344      \param bbox  parameters
345      \param ctm   do yet
346     */
347     void print(SPPrintContext *ctx, NRRect const *pbox, NRRect const *dbox, NRRect const *bbox, Geom::Matrix const &ctm) const;
349 #ifdef HAVE_CAIRO_PDF    
350     /** Renders all the glyphs to the given Cairo rendering context.
351      \param ctx   The Cairo rendering context to be used
352      */
353     void showGlyphs(CairoRenderContext *ctx) const;
354 #endif
356     /** debug and unit test method. Creates a textual representation of the
357     contents of this object. The output is designed to be both human-readable
358     and comprehensible when diffed with a known-good dump. */
359     Glib::ustring dumpAsText() const;
361     /** Moves all the glyphs in the structure so that the baseline of all
362     the characters sits neatly along the path specified. If the text has
363     more than one line the results are undefined. The 'align' means to
364     use the SVG align method as documented in SVG1.1 section 10.13.2.
365     NB: njh has suggested that it would be cool if we could flow from
366     shape to path and back again. This is possible, so this method will be
367     removed at some point.
368     A pointer to \a path is retained by the class for use by the cursor
369     positioning functions. */
370     void fitToPathAlign(SVGLength const &startOffset, Path const &path);
372     /** Convert the specified range of characters into their bezier 
373     outlines.
374     */
375     SPCurve* convertToCurves(iterator const &from_glyph, iterator const &to_glyph) const;
376     inline SPCurve* convertToCurves() const;
378     /** Apply the given transform to all the output presently stored in
379     this object. This only transforms the glyph positions, The glyphs
380     themselves will not be transformed. */
381     void transform(Geom::Matrix const &transform);
383     //@}
385     // **********
387     /** \name Output (Iterators)
388       Methods for operating with the Layout::iterator class. The method
389       names ending with 'Index' return 0-based offsets of the number of
390       items since the beginning of the flow.
391     */
392     //@{
394     /** Returns an iterator pointing at the first glyph of the flowed output.
395     The first glyph is also the first character, line, paragraph, etc. */
396     inline iterator begin() const;
398     /** Returns an iterator pointing just past the end of the last glyph,
399     which is also just past the end of the last chunk, span, etc, etc. */
400     inline iterator end() const;
402     /** Returns an iterator pointing at the given character index. This
403     index should be related to the result from a prior call to
404     iteratorToCharIndex(). */
405     inline iterator charIndexToIterator(int char_index) const;
407     /** Returns the character index from the start of the flow represented
408     by the given iterator. This number isn't very useful, except for when
409     editing text it will stay valid across calls to computeFlow() and will
410     change in predictable ways when characters are added and removed. It's
411     also useful when transitioning old code. */
412     inline int iteratorToCharIndex(iterator const &it) const;
414     /** Checks the validity of the given iterator over the current layout.
415     If it points to a position out of the bounds for this layout it will
416     be corrected to the nearest valid position. If you pass an iterator
417     belonging to a different layout it will be converted to one for this
418     layout. */
419     inline void validateIterator(iterator *it) const;
421     /** Returns an iterator pointing to the cursor position for a mouse
422     click at the given coordinates. */
423     iterator getNearestCursorPositionTo(double x, double y) const;
424     inline iterator getNearestCursorPositionTo(Geom::Point const &point) const;
426     /** Returns an iterator pointing to the letter whose bounding box contains
427     the given coordinates. end() if the point is not over any letter. The
428     iterator will \em not point at the specific glyph within the character. */
429     iterator getLetterAt(double x, double y) const;
430     inline iterator getLetterAt(Geom::Point &point) const;
432     /** Returns an iterator pointing to the character in the output which
433     was created from the given input. If the character at the given byte
434     offset was removed (soft hyphens, for example) the next character after
435     it is returned. If no input was added with the given cookie, end() is
436     returned. If more than one input has the same cookie, the first will
437     be used regardless of the value of \a text_iterator. If
438     \a text_iterator is out of bounds, the first or last character belonging
439     to the given input will be returned accordingly. */
440     iterator sourceToIterator(void *source_cookie, Glib::ustring::const_iterator text_iterator) const;
442     /** Returns an iterator pointing to the first character in the output
443     which was created from the given source. If \a source_cookie is invalid,
444     end() is returned. If more than one input has the same cookie, the
445     first one will be used. */
446     iterator sourceToIterator(void *source_cookie) const;
448     // many functions acting on iterators, most of which are obvious
449     // also most of them don't check that \a it != end(). Be careful.
451     /** Returns the bounding box of the given glyph, and its rotation.
452     The centre of rotation is the horizontal centre of the box at the
453     text baseline. */
454     Geom::OptRect glyphBoundingBox(iterator const &it, double *rotation) const;
456     /** Returns the zero-based line number of the character pointed to by
457     \a it. */
458     inline unsigned lineIndex(iterator const &it) const;
460     /** Returns the zero-based number of the shape which contains the
461     character pointed to by \a it. */
462     inline unsigned shapeIndex(iterator const &it) const;
464     /** Returns true if the character at \a it is a whitespace, as defined
465     by Pango. This is not meant to be used for picking out words from the
466     output, use iterator::nextStartOfWord() and friends instead. */
467     inline bool isWhitespace(iterator const &it) const;
469     /** Returns the unicode character code of the character pointed to by
470     \a it. If \a it == end() the result is undefined. */
471     inline int characterAt(iterator const &it) const;
473     /** Discovers where the character pointed to by \a it came from, by
474     retrieving the cookie that was passed to the call to appendText() or
475     appendControlCode() which generated that output. If \a it == end()
476     then NULL is returned as the cookie. If the character was generated
477     from a call to appendText() then the optional \a text_iterator
478     parameter is set to point to the actual character, otherwise
479     \a text_iterator is unaltered. */
480     void getSourceOfCharacter(iterator const &it, void **source_cookie, Glib::ustring::iterator *text_iterator = NULL) const;
482     /** For latin text, the left side of the character, on the baseline */
483     Geom::Point characterAnchorPoint(iterator const &it) const;
485     /** For left aligned text, the leftmost end of the baseline
486     For rightmost text, the rightmost... you probably got it by now ;-)*/
487     boost::optional<Geom::Point> baselineAnchorPoint() const;
489     /** This is that value to apply to the x,y attributes of tspan role=line
490     elements, and hence it takes alignment into account. */
491     Geom::Point chunkAnchorPoint(iterator const &it) const;
493     /** Returns the box extents (not ink extents) of the given character.
494     The centre of rotation is at the horizontal centre of the box on the
495     text baseline. */
496     Geom::Rect characterBoundingBox(iterator const &it, double *rotation = NULL) const;
498     /** Basically uses characterBoundingBox() on all the characters from
499     \a start to \a end and returns the union of these boxes. The return value
500     is a list of zero or more quadrilaterals specified by a group of four
501     points for each, thus size() is always a multiple of four. */
502     std::vector<Geom::Point> createSelectionShape(iterator const &it_start, iterator const &it_end, Geom::Matrix const &transform) const;
504     /** Returns true if \a it points to a character which is a valid cursor
505     position, as defined by Pango. */
506     inline bool isCursorPosition(iterator const &it) const;
508     /** Gets the ideal cursor shape for a given iterator. The result is
509     undefined if \a it is not at a valid cursor position.
510       \param it        The location in the output
511       \param position  The pixel location of the centre of the 'bottom' of
512                        the cursor.
513       \param height    The height in pixels of the surrounding text
514       \param rotation  The angle to draw from \a position. Radians, zero up,
515                        increasing clockwise.
516     */
517     void queryCursorShape(iterator const &it, Geom::Point &position, double &height, double &rotation) const;
519     /** Returns true if \a it points to a character which is a the start of
520     a word, as defined by Pango. */
521     inline bool isStartOfWord(iterator const &it) const;
523     /** Returns true if \a it points to a character which is a the end of
524     a word, as defined by Pango. */
525     inline bool isEndOfWord(iterator const &it) const;
527     /** Returns true if \a it points to a character which is a the start of
528     a sentence, as defined by Pango. */
529     inline bool isStartOfSentence(iterator const &it) const;
531     /** Returns true if \a it points to a character which is a the end of
532     a sentence, as defined by Pango. */
533     inline bool isEndOfSentence(iterator const &it) const;
535     /** Returns the zero-based number of the paragraph containing the
536     character pointed to by \a it. */
537     inline unsigned paragraphIndex(iterator const &it) const;
539     /** Returns the actual alignment used for the paragraph containing
540     the character pointed to by \a it. This means that the CSS 'start'
541     and 'end' are correctly translated into LEFT or RIGHT according to
542     the paragraph's directionality. For vertical text, LEFT is top
543     alignment and RIGHT is bottom. */
544     inline Alignment paragraphAlignment(iterator const &it) const;
546     /** Returns kerning information which could cause the current output
547     to be exactly reproduced if the letter and word spacings were zero and
548     full justification was not used. The x and y arrays are not used, but
549     they are cleared. The dx applied to the first character in a chunk
550     will always be zero. If the region between \a from and \a to crosses
551     a line break then the results may be surprising, and are undefined.
552     Trailing zeros on the returned arrays will be trimmed. */
553     void simulateLayoutUsingKerning(iterator const &from, iterator const &to, OptionalTextTagAttrs *result) const;
555     //@}
557     /// it's useful for this to be public so that ScanlineMaker can use it
558     struct LineHeight {
559         double ascent;
560         double descent;
561         double leading;
562         inline double total() const {return ascent + descent + leading;}
563         inline void setZero() {ascent = descent = leading = 0.0;}
564         inline LineHeight& operator*=(double x) {ascent *= x; descent *= x; leading *= x; return *this;}
565         void max(LineHeight const &other);   /// makes this object contain the largest of all three members between this object and other
566     };
568     /// see _enum_converter()
569     struct EnumConversionItem {
570         int input, output;
571     };
573 private:
574     /** Erases all the stuff set by the owner as input, ie #_input_stream
575     and #_input_wrap_shapes. */
576     void _clearInputObjects();
578     /** Erases all the stuff output by computeFlow(). Glyphs and things. */
579     void _clearOutputObjects();
581     static const gunichar UNICODE_SOFT_HYPHEN;
583     // ******************* input flow
585     enum InputStreamItemType {TEXT_SOURCE, CONTROL_CODE};
587     class InputStreamItem {
588     public:
589         virtual ~InputStreamItem() {}
590         virtual InputStreamItemType Type() =0;
591         void *source_cookie;
592     };
594     /** Represents a text item in the input stream. See #_input_stream.
595     Most of the members are copies of the values passed to appendText(). */
596     class InputStreamTextSource : public InputStreamItem {
597     public:
598         virtual InputStreamItemType Type() {return TEXT_SOURCE;}
599         virtual ~InputStreamTextSource();
600         Glib::ustring const *text;    /// owned by the caller
601         Glib::ustring::const_iterator text_begin, text_end;
602         int text_length;    /// in characters, from text_start to text_end only
603         SPStyle *style;
604         /** These vectors can (often will) be shorter than the text
605         in this source, but never longer. */
606         std::vector<SVGLength> x;
607         std::vector<SVGLength> y;
608         std::vector<SVGLength> dx;
609         std::vector<SVGLength> dy;
610         std::vector<SVGLength> rotate;
611         
612         // a few functions for some of the more complicated style accesses
613         float styleComputeFontSize() const;
614         /// The return value must be freed with pango_font_description_free()
615         PangoFontDescription *styleGetFontDescription() const;
616         font_instance *styleGetFontInstance() const;
617         Direction styleGetBlockProgression() const;
618         Alignment styleGetAlignment(Direction para_direction, bool try_text_align) const;
619     };
621     /** Represents a control code item in the input stream. See
622     #_input_streams. All the members are copies of the values passed to
623     appendControlCode(). */
624     class InputStreamControlCode : public InputStreamItem {
625     public:
626         virtual InputStreamItemType Type() {return CONTROL_CODE;}
627         TextControlCode code;
628         double ascent;
629         double descent;
630         double width;
631     };
633     /** This is our internal storage for all the stuff passed to the
634     appendText() and appendControlCode() functions. */
635     std::vector<InputStreamItem*> _input_stream;
637     /** The parameters to appendText() are allowed to be a little bit
638     complex. This copies them to be the right length and starting at zero.
639     We also don't want to write five bits of identical code just with
640     different variable names. */
641     static void _copyInputVector(std::vector<SVGLength> const &input_vector, unsigned input_offset, std::vector<SVGLength> *output_vector, size_t max_length);
643     /** There are a few cases where we have different sets of enums meaning
644     the same thing, eg Pango font styles vs. SPStyle font styles. These need
645     converting. */
646     static int _enum_converter(int input, EnumConversionItem const *conversion_table, unsigned conversion_table_size);
648     /** The overall block-progression of the whole flow. */
649     inline Direction _blockProgression() const
650         {return static_cast<InputStreamTextSource*>(_input_stream.front())->styleGetBlockProgression();}
652     /** so that LEFT_TO_RIGHT == RIGHT_TO_LEFT but != TOP_TO_BOTTOM */
653     static bool _directions_are_orthogonal(Direction d1, Direction d2);
655     /** If the output is empty callers still want to be able to call
656     queryCursorShape() and get a valid answer so, while #_input_wrap_shapes
657     can still be considered valid, we need to precompute the cursor shape
658     for this case. */
659     void _calculateCursorShapeForEmpty();
661     struct CursorShape {
662         Geom::Point position;
663         double height;
664         double rotation;
665     } _empty_cursor_shape;
667     // ******************* input shapes
669     struct InputWrapShape {
670         Shape const *shape;        /// as passed to Layout::appendWrapShape()
671         DisplayAlign display_align;   /// as passed to Layout::appendWrapShape()
672     };
673     std::vector<InputWrapShape> _input_wrap_shapes;
675     // ******************* output
677     /** as passed to fitToPathAlign() */
678     Path const *_path_fitted;
680     struct Glyph;
681     struct Character;
682     struct Span;
683     struct Chunk;
684     struct Line;
685     struct Paragraph;
687     struct Glyph {
688         int glyph;
689         unsigned in_character;
690         float x;         /// relative to the start of the chunk
691         float y;         /// relative to the current line's baseline
692         float rotation;  /// absolute, modulo any object transforms, which we don't know about
693         float width;
694         inline Span const & span(Layout const *l) const {return l->_spans[l->_characters[in_character].in_span];}
695         inline Chunk const & chunk(Layout const *l) const {return l->_chunks[l->_spans[l->_characters[in_character].in_span].in_chunk];}
696         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];}
697     };
698     struct Character {
699         unsigned in_span;
700         float x;      /// relative to the start of the *span* (so we can do block-progression)
701         PangoLogAttr char_attributes;
702         int in_glyph;   /// will be -1 if this character has no visual representation
703         inline Span const & span(Layout const *l) const {return l->_spans[in_span];}
704         inline Chunk const & chunk(Layout const *l) const {return l->_chunks[l->_spans[in_span].in_chunk];}
705         inline Line const & line(Layout const *l) const {return l->_lines[l->_chunks[l->_spans[in_span].in_chunk].in_line];}
706         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];}
707         // 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
708     };
709     struct Span {
710         unsigned in_chunk;
711         font_instance *font;
712         float font_size;
713         float x_start;   /// relative to the start of the chunk
714         float x_end;     /// relative to the start of the chunk
715         LineHeight line_height;
716         double baseline_shift;  /// relative to the line's baseline
717         Direction direction;     /// See CSS3 section 3.2. Either rtl or ltr
718         Direction block_progression;  /// See CSS3 section 3.2. The direction in which lines go.
719         unsigned in_input_stream_item;
720         Glib::ustring::const_iterator input_stream_first_character;
721         inline Chunk const & chunk(Layout const *l) const {return l->_chunks[in_chunk];}
722         inline Line const & line(Layout const *l) const {return l->_lines[l->_chunks[in_chunk].in_line];}
723         inline Paragraph const & paragraph(Layout const *l) const {return l->_paragraphs[l->_lines[l->_chunks[in_chunk].in_line].in_paragraph];}
724     };
725     struct Chunk {
726         unsigned in_line;
727         double left_x;
728     };
729     struct Line {
730         unsigned in_paragraph;
731         double baseline_y;
732         unsigned in_shape;
733     };
734     struct Paragraph {
735         Direction base_direction;    /// can be overridden by child Span objects
736         Alignment alignment;
737     };
738     std::vector<Paragraph> _paragraphs;
739     std::vector<Line> _lines;
740     std::vector<Chunk> _chunks;
741     std::vector<Span> _spans;
742     std::vector<Character> _characters;
743     std::vector<Glyph> _glyphs;
745     /** gets the overall matrix that transforms the given glyph from local
746     space to world space. */
747     void _getGlyphTransformMatrix(int glyph_index, Geom::Matrix *matrix) const;
749     // loads of functions to drill down the object tree, all of them
750     // annoyingly similar and all of them requiring predicate functors.
751     // I'll be buggered if I can find a way to make it work with
752     // functions or with a templated functor, so macros it is.
753 #define EMIT_PREDICATE(name, object_type, index_generator)                  \
754     class name {                                                            \
755         Layout const * const _flow;                                         \
756     public:                                                                 \
757         inline name(Layout const *flow) : _flow(flow) {}                    \
758         inline bool operator()(object_type const &object, unsigned index)   \
759             {return index_generator < index;}                               \
760     }
761 // end of macro
762     EMIT_PREDICATE(PredicateLineToSpan,        Span,      _flow->_chunks[object.in_chunk].in_line);
763     EMIT_PREDICATE(PredicateLineToCharacter,   Character, _flow->_chunks[_flow->_spans[object.in_span].in_chunk].in_line);
764     EMIT_PREDICATE(PredicateSpanToCharacter,   Character, object.in_span);
765     EMIT_PREDICATE(PredicateSourceToCharacter, Character, _flow->_spans[object.in_span].in_input_stream_item);
767     inline unsigned _lineToSpan(unsigned line_index) const
768         {return std::lower_bound(_spans.begin(), _spans.end(), line_index, PredicateLineToSpan(this)) - _spans.begin();}
769     inline unsigned _lineToCharacter(unsigned line_index) const
770         {return std::lower_bound(_characters.begin(), _characters.end(), line_index, PredicateLineToCharacter(this)) - _characters.begin();}
771     inline unsigned _spanToCharacter(unsigned span_index) const
772         {return std::lower_bound(_characters.begin(), _characters.end(), span_index, PredicateSpanToCharacter(this)) - _characters.begin();}
773     inline unsigned _sourceToCharacter(unsigned source_index) const
774         {return std::lower_bound(_characters.begin(), _characters.end(), source_index, PredicateSourceToCharacter(this)) - _characters.begin();}
776     /** given an x coordinate and a line number, returns an iterator
777     pointing to the closest cursor position on that line to the
778     coordinate. */
779     iterator _cursorXOnLineToIterator(unsigned line_index, double local_x) const;
781     /** calculates the width of a chunk, which is the largest x
782     coordinate (start or end) of the spans contained within it. */
783     double _getChunkWidth(unsigned chunk_index) const;
784 };
786 /** \brief Holds a position within the glyph output of Layout.
788 Used to access the output of a Layout, query information and generally
789 move around in it. See Layout for a glossary of the names of functions.
791 I'm not going to document all the methods because most of their names make
792 their function self-evident.
794 A lot of the functions would do the same thing in a naive implementation
795 for latin-only text, for example nextCharacter(), nextCursorPosition() and
796 cursorRight(). Generally it's fairly obvious which one you should use in a
797 given situation, but sometimes you might need to put some thought in to it.
799 All the methods return false if the requested action would have caused the
800 current position to move out of bounds. In this case the position is moved
801 to either begin() or end(), depending on which direction you were going.
803 Note that some characters do not have a glyph representation (eg line
804 breaks), so if you try using prev/nextGlyph() from one of these you're
805 heading for a crash.
806 */
807 class Layout::iterator {
808 public:
809     friend class Layout;
810     // this is just so you can create uninitialised iterators - don't actually try to use one
811     iterator() : _parent_layout(NULL) {}
812     // no copy constructor required, the default does what we want
813     bool operator== (iterator const &other) const
814         {return _glyph_index == other._glyph_index && _char_index == other._char_index;}
815     bool operator!= (iterator const &other) const
816         {return _glyph_index != other._glyph_index || _char_index != other._char_index;}
818     /* mustn't compare _glyph_index in these operators because for characters
819     that don't have glyphs (line breaks, elided soft hyphens, etc), the glyph
820     index is -1 which makes them not well-ordered. To be honest, interating by
821     glyphs is not very useful and should be avoided. */
822     bool operator< (iterator const &other) const
823         {return _char_index < other._char_index;}
824     bool operator<= (iterator const &other) const
825         {return _char_index <= other._char_index;}
826     bool operator> (iterator const &other) const
827         {return _char_index > other._char_index;}
828     bool operator>= (iterator const &other) const
829         {return _char_index >= other._char_index;}
831     /* **** visual-oriented methods **** */
833     //glyphs
834     inline bool prevGlyph();
835     inline bool nextGlyph();
837     //span
838     bool prevStartOfSpan();
839     bool thisStartOfSpan();
840     bool nextStartOfSpan();
842     //chunk
843     bool prevStartOfChunk();
844     bool thisStartOfChunk();
845     bool nextStartOfChunk();
847     //line
848     bool prevStartOfLine();
849     bool thisStartOfLine();
850     bool nextStartOfLine();
851     bool thisEndOfLine();
853     //shape
854     bool prevStartOfShape();
855     bool thisStartOfShape();
856     bool nextStartOfShape();
858     /* **** text-oriented methods **** */
860     //characters
861     inline bool nextCharacter();
862     inline bool prevCharacter();
864     bool nextCursorPosition();
865     bool prevCursorPosition();
866     bool nextLineCursor(int n = 1);
867     bool prevLineCursor(int n = 1);
869     //words
870     bool nextStartOfWord();
871     bool prevStartOfWord();
872     bool nextEndOfWord();
873     bool prevEndOfWord();
875     //sentences
876     bool nextStartOfSentence();
877     bool prevStartOfSentence();
878     bool nextEndOfSentence();
879     bool prevEndOfSentence();
881     //paragraphs
882     bool prevStartOfParagraph();
883     bool thisStartOfParagraph();
884     bool nextStartOfParagraph();
885     //no endOfPara methods because that's just the previous char
887     //sources
888     bool prevStartOfSource();
889     bool thisStartOfSource();
890     bool nextStartOfSource();
892     //logical cursor movement
893     bool cursorUp(int n = 1);
894     bool cursorDown(int n = 1);
895     bool cursorLeft();
896     bool cursorRight();
898     //logical cursor movement (by word or paragraph)
899     bool cursorUpWithControl();
900     bool cursorDownWithControl();
901     bool cursorLeftWithControl();
902     bool cursorRightWithControl();
904 private:
905     Layout const *_parent_layout;
906     int _glyph_index;      /// index into Layout::glyphs, or -1
907     unsigned _char_index;       /// index into Layout::character
908     bool _cursor_moving_vertically;
909     /** for cursor up/down movement we must maintain the x position where
910     we started so the cursor doesn't 'drift' left or right with the repeated
911     quantization to character boundaries. */
912     double _x_coordinate;
914     inline iterator(Layout const *p, unsigned c, int g)
915         : _parent_layout(p), _glyph_index(g), _char_index(c), _cursor_moving_vertically(false), _x_coordinate(0.0) {}
916     inline iterator(Layout const *p, unsigned c)
917         : _parent_layout(p), _glyph_index(p->_characters[c].in_glyph), _char_index(c), _cursor_moving_vertically(false), _x_coordinate(0.0) {}
918     // no dtor required
919     void beginCursorUpDown();  /// stores the current x coordinate so that the cursor won't drift. See #_x_coordinate
921     /** moves forward or backwards one cursor position according to the
922     directionality of the current paragraph, but ignoring block progression.
923     Helper for the cursor*() functions. */
924     bool _cursorLeftOrRightLocalX(Direction direction);
926     /** moves forward or backwards by until the next character with
927     is_word_start according to the directionality of the current paragraph,
928     but ignoring block progression. Helper for the cursor*WithControl()
929     functions. */
930     bool _cursorLeftOrRightLocalXByWord(Direction direction);
931 };
933 // ************************** inline methods
935 inline SPCurve* Layout::convertToCurves() const
936     {return convertToCurves(begin(), end());}
938 inline Layout::iterator Layout::begin() const
939     {return iterator(this, 0, 0);}
941 inline Layout::iterator Layout::end() const
942     {return iterator(this, _characters.size(), _glyphs.size());}
944 inline Layout::iterator Layout::charIndexToIterator(int char_index) const
946     if (char_index < 0) return begin();
947     if (char_index >= (int)_characters.size()) return end();
948     return iterator(this, char_index);
951 inline int Layout::iteratorToCharIndex(Layout::iterator const &it) const
952     {return it._char_index;}
954 inline void Layout::validateIterator(Layout::iterator *it) const
956     it->_parent_layout = this;
957     if (it->_char_index >= _characters.size()) {
958         it->_char_index = _characters.size();
959         it->_glyph_index = _glyphs.size();
960     } else
961         it->_glyph_index = _characters[it->_char_index].in_glyph;
964 inline Layout::iterator Layout::getNearestCursorPositionTo(Geom::Point const &point) const
965     {return getNearestCursorPositionTo(point[0], point[1]);}
967 inline Layout::iterator Layout::getLetterAt(Geom::Point &point) const
968     {return getLetterAt(point[0], point[1]);}
970 inline unsigned Layout::lineIndex(iterator const &it) const
971     {return it._char_index == _characters.size() ? _lines.size() - 1 : _characters[it._char_index].chunk(this).in_line;}
973 inline unsigned Layout::shapeIndex(iterator const &it) const
974     {return it._char_index == _characters.size() ? _input_wrap_shapes.size() - 1 : _characters[it._char_index].line(this).in_shape;}
976 inline bool Layout::isWhitespace(iterator const &it) const
977     {return it._char_index == _characters.size() || _characters[it._char_index].char_attributes.is_white;}
979 inline int Layout::characterAt(iterator const &it) const
981     void *unused;
982     Glib::ustring::iterator text_iter;
983     getSourceOfCharacter(it, &unused, &text_iter);
984     return *text_iter;
987 inline bool Layout::isCursorPosition(iterator const &it) const
988     {return it._char_index == _characters.size() || _characters[it._char_index].char_attributes.is_cursor_position;}
990 inline bool Layout::isStartOfWord(iterator const &it) const
991     {return it._char_index != _characters.size() && _characters[it._char_index].char_attributes.is_word_start;}
993 inline bool Layout::isEndOfWord(iterator const &it) const
994     {return it._char_index == _characters.size() || _characters[it._char_index].char_attributes.is_word_end;}
996 inline bool Layout::isStartOfSentence(iterator const &it) const
997     {return it._char_index != _characters.size() && _characters[it._char_index].char_attributes.is_sentence_start;}
999 inline bool Layout::isEndOfSentence(iterator const &it) const
1000     {return it._char_index == _characters.size() || _characters[it._char_index].char_attributes.is_sentence_end;}
1002 inline unsigned Layout::paragraphIndex(iterator const &it) const
1003     {return it._char_index == _characters.size() ? _paragraphs.size() - 1 : _characters[it._char_index].line(this).in_paragraph;}
1005 inline Layout::Alignment Layout::paragraphAlignment(iterator const &it) const
1006     {return _paragraphs[paragraphIndex(it)].alignment;}
1008 inline bool Layout::iterator::nextGlyph()
1010     _cursor_moving_vertically = false;
1011     if (_glyph_index >= (int)_parent_layout->_glyphs.size() - 1) {
1012         if (_glyph_index == (int)_parent_layout->_glyphs.size()) return false;
1013         _char_index = _parent_layout->_characters.size();
1014         _glyph_index = _parent_layout->_glyphs.size();
1015     }
1016     else _char_index = _parent_layout->_glyphs[++_glyph_index].in_character;
1017     return true;
1020 inline bool Layout::iterator::prevGlyph()
1022     _cursor_moving_vertically = false;
1023     if (_glyph_index == 0) return false;
1024     _char_index = _parent_layout->_glyphs[--_glyph_index].in_character;
1025     return true;
1028 inline bool Layout::iterator::nextCharacter()
1030     _cursor_moving_vertically = false;
1031     if (_char_index + 1 >= _parent_layout->_characters.size()) {
1032         if (_char_index == _parent_layout->_characters.size()) return false;
1033         _char_index = _parent_layout->_characters.size();
1034         _glyph_index = _parent_layout->_glyphs.size();
1035     }
1036     else _glyph_index = _parent_layout->_characters[++_char_index].in_glyph;
1037     return true;
1040 inline bool Layout::iterator::prevCharacter()
1042     _cursor_moving_vertically = false;
1043     if (_char_index == 0) return false;
1044     _glyph_index = _parent_layout->_characters[--_char_index].in_glyph;
1045     return true;
1048 }//namespace Text
1049 }//namespace Inkscape
1051 #endif
1054 /*
1055   Local Variables:
1056   mode:c++
1057   c-file-style:"stroustrup"
1058   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
1059   indent-tabs-mode:nil
1060   fill-column:99
1061   End:
1062 */
1063 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :