2
* Inkscape::Text::Layout::ScanlineMaker - text layout engine shape measurers
5
* Richard Hughes <cyreve@users.sf.net>
7
* Copyright (C) 2005 Richard Hughes
9
* Released under GNU GPL, read the file 'COPYING' for more information
11
#ifndef __LAYOUT_TNG_SCANLINE_MAKER_H__
12
#define __LAYOUT_TNG_SCANLINE_MAKER_H__
16
#include "libnrtype/Layout-TNG.h"
23
/** \brief private to Layout. Generates lists of chunks within a shape.
25
This is the abstract base class for taking a given shape and scanning through
26
it line-by-line to get the horizontal extents of each chunk for a line of a
27
given height. There are two specialisations: One for real shapes and one that
28
turns off wrapping by simulating an infinite shape. In due course there will
29
be a further specialisation to optimise for the common case where the shape
32
class Layout::ScanlineMaker
35
virtual ~ScanlineMaker() {}
38
double y; /// that's the top of the scan run, not the baseline
39
double x_start; // these are not flipped according to the text direction
41
inline double width() const {return std::abs(x_start - x_end);}
44
/** Returns a list of chunks on the current line which can fit text with
45
the given properties. It is up to the caller to discard any chunks which
46
are too narrow for its needs. This function may change the y coordinate
47
between calls if the new height too big to fit in the space remaining in
48
this shape. Returns an empty vector if there is no space left in the
50
virtual std::vector<ScanRun> makeScanline(Layout::LineHeight const &line_height) =0;
52
/** Indicates that the caller has successfully filled the current line
53
and hence that the next call to makeScanline() should return lines on
54
the next lower line. There is no error return, the next call to
55
makeScanline() will give an error if there is no more space. */
56
virtual void completeLine() =0;
58
/** Returns the y coordinate of the top of the scanline that will be
59
returned by the next call to makeScanline(). */
60
virtual double yCoordinate() = 0;
62
/** Forces an arbitrary change in the stored y coordinate of the object.
63
The next call to makeScanline() will return runs whose top is at
64
the new coordinate. */
65
virtual void setNewYCoordinate(double new_y) =0;
67
/** Tests whether the caller can fit a new line with the given metrics
68
into exactly the space returned by the previous call to makeScanline().
69
This saves the caller from having to discard its wrapping solution and
70
starting at the beginning of the line again when a larger font is seen.
71
The metrics given here are considered to be the ones that are being
72
used now, and hence is the line advance height used by completeLine().
74
virtual bool canExtendCurrentScanline(Layout::LineHeight const &line_height) =0;
77
/** \brief private to Layout. Generates infinite scanlines for when you don't want wrapping
79
This is a 'fake' scanline maker which will always return infinite results,
80
effectively turning off wrapping. It's a very simple implementation.
82
It does have the curious property, however, that the input coordinates are
83
'real' x and y, but the outputs are rotated according to the
86
class Layout::InfiniteScanlineMaker : public Layout::ScanlineMaker
89
InfiniteScanlineMaker(double initial_x, double initial_y, Layout::Direction block_progression);
90
virtual ~InfiniteScanlineMaker();
92
/** Returns a single infinite run at the current location */
93
virtual std::vector<ScanRun> makeScanline(Layout::LineHeight const &line_height);
95
/** Increments the current y by the current line height */
96
virtual void completeLine();
98
virtual double yCoordinate()
101
/** Just changes y */
102
virtual void setNewYCoordinate(double new_y);
104
/** Always true, but has to save the new height */
105
virtual bool canExtendCurrentScanline(Layout::LineHeight const &line_height);
109
Layout::LineHeight _current_line_height;
110
bool _negative_block_progression; /// if true, indicates that completeLine() should decrement rather than increment, ie block-progression is either rl or bt
113
/** \brief private to Layout. Generates scanlines inside an arbitrary shape
115
This is the 'perfect', and hence slowest, implementation of a
116
Layout::ScanlineMaker, which will return exact bounds for any given
119
class Layout::ShapeScanlineMaker : public Layout::ScanlineMaker
122
ShapeScanlineMaker(Shape const *shape, Layout::Direction block_progression);
123
virtual ~ShapeScanlineMaker();
125
virtual std::vector<ScanRun> makeScanline(Layout::LineHeight const &line_height);
127
virtual void completeLine();
129
virtual double yCoordinate();
131
virtual void setNewYCoordinate(double new_y);
134
virtual bool canExtendCurrentScanline(Layout::LineHeight const &line_height);
136
/** To generate scanlines for top-to-bottom text it is easiest if we
137
simply rotate the given shape by a multiple of 90 degrees. This stores
138
that. If no rotation was needed we can simply store the pointer we were
139
given and set shape_needs_freeing appropriately. */
140
Shape *_rotated_shape;
142
/// see #rotated_shape;
143
bool _shape_needs_freeing;
145
// Shape::BeginRaster() needs floats rather than doubles
146
float _bounding_box_top, _bounding_box_bottom;
149
int _current_rasterization_point;
150
float _current_line_height;
152
bool _negative_block_progression; /// if true, indicates that completeLine() should decrement rather than increment, ie block-progression is either rl or bt
156
}//namespace Inkscape
163
c-file-style:"stroustrup"
164
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
169
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :