~valavanisalex/ubuntu/precise/inkscape/fix-943984

« back to all changes in this revision

Viewing changes to inkscape-0.47pre1/src/libnrtype/Layout-TNG-Scanline-Makers.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Bryce Harrington
  • Date: 2009-07-02 17:09:45 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20090702170945-nn6d6zswovbwju1t
Tags: 0.47~pre1-0ubuntu1
* New upstream release.
  - Don't constrain maximization on small resolution devices (pre0)
    (LP: #348842)
  - Fixes segfault on startup (pre0)
    (LP: #391149)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Inkscape::Text::Layout::ScanlineMaker - text layout engine shape measurers
 
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
#include "Layout-TNG-Scanline-Maker.h"
 
12
#include "livarot/Shape.h"
 
13
#include "livarot/float-line.h"
 
14
 
 
15
namespace Inkscape {
 
16
namespace Text {
 
17
 
 
18
// *********************** infinite version
 
19
 
 
20
Layout::InfiniteScanlineMaker::InfiniteScanlineMaker(double initial_x, double initial_y, Layout::Direction block_progression)
 
21
{
 
22
    _current_line_height.ascent = 0.0;
 
23
    _current_line_height.descent = 0.0;
 
24
    _current_line_height.leading = 0.0;
 
25
    switch (block_progression) {
 
26
        case LEFT_TO_RIGHT:
 
27
        case RIGHT_TO_LEFT:
 
28
            _x = initial_y;
 
29
            _y = initial_x;
 
30
            break;
 
31
        default:
 
32
            _x = initial_x;
 
33
            _y = initial_y;
 
34
            break;
 
35
    }
 
36
    _negative_block_progression = block_progression == RIGHT_TO_LEFT || block_progression == BOTTOM_TO_TOP;
 
37
        
 
38
}
 
39
 
 
40
Layout::InfiniteScanlineMaker::~InfiniteScanlineMaker()
 
41
{
 
42
}
 
43
 
 
44
std::vector<Layout::ScanlineMaker::ScanRun> Layout::InfiniteScanlineMaker::makeScanline(Layout::LineHeight const &line_height)
 
45
{
 
46
    std::vector<ScanRun> runs(1);
 
47
    runs[0].x_start = _x;
 
48
    runs[0].x_end = FLT_MAX;   // we could use DBL_MAX, but this just seems safer
 
49
    runs[0].y = _y;
 
50
    _current_line_height = line_height;
 
51
    return runs;
 
52
}
 
53
 
 
54
void Layout::InfiniteScanlineMaker::completeLine()
 
55
{
 
56
    if (_negative_block_progression)
 
57
        _y -= _current_line_height.total();
 
58
    else
 
59
        _y += _current_line_height.total();
 
60
    _current_line_height.ascent = 0.0;
 
61
    _current_line_height.descent = 0.0;
 
62
    _current_line_height.leading = 0.0;
 
63
}
 
64
 
 
65
void Layout::InfiniteScanlineMaker::setNewYCoordinate(double new_y)
 
66
{
 
67
    _y = new_y;
 
68
}
 
69
 
 
70
bool Layout::InfiniteScanlineMaker::canExtendCurrentScanline(Layout::LineHeight const &line_height)
 
71
{
 
72
    _current_line_height = line_height;
 
73
    return true;
 
74
}
 
75
 
 
76
// *********************** real shapes version
 
77
 
 
78
Layout::ShapeScanlineMaker::ShapeScanlineMaker(Shape const *shape, Layout::Direction block_progression)
 
79
{
 
80
    if (block_progression == TOP_TO_BOTTOM) {
 
81
        _rotated_shape = const_cast<Shape*>(shape);
 
82
        _shape_needs_freeing = false;
 
83
    } else {
 
84
        Shape *temp_rotated_shape = new Shape;
 
85
        _shape_needs_freeing = true;
 
86
        temp_rotated_shape->Copy(const_cast<Shape*>(shape));
 
87
        switch (block_progression) {
 
88
            case BOTTOM_TO_TOP: temp_rotated_shape->Transform(Geom::Matrix(1.0, 0.0, 0.0, -1.0, 0.0, 0.0)); break;  // reflect about x axis
 
89
            case LEFT_TO_RIGHT: temp_rotated_shape->Transform(Geom::Matrix(0.0, 1.0, 1.0, 0.0, 0.0, 0.0)); break;   // reflect about y=x
 
90
            case RIGHT_TO_LEFT: temp_rotated_shape->Transform(Geom::Matrix(0.0, -1.0, 1.0, 0.0, 0.0, 0.0)); break;  // reflect about y=-x
 
91
            default: break;
 
92
        }
 
93
        _rotated_shape = new Shape;
 
94
        _rotated_shape->ConvertToShape(temp_rotated_shape);
 
95
        delete temp_rotated_shape;
 
96
    }
 
97
    _rotated_shape->CalcBBox(true);
 
98
    _bounding_box_top = _rotated_shape->topY;
 
99
    _bounding_box_bottom = _rotated_shape->bottomY;
 
100
    _y = _rasterizer_y = _bounding_box_top;
 
101
    _current_rasterization_point = 0;
 
102
    _rotated_shape->BeginRaster(_y, _current_rasterization_point);
 
103
    _negative_block_progression = block_progression == RIGHT_TO_LEFT || block_progression == BOTTOM_TO_TOP;
 
104
}
 
105
 
 
106
 
 
107
Layout::ShapeScanlineMaker::~ShapeScanlineMaker()
 
108
{
 
109
    _rotated_shape->EndRaster();  
 
110
    if (_shape_needs_freeing)
 
111
        delete _rotated_shape;
 
112
}
 
113
 
 
114
std::vector<Layout::ScanlineMaker::ScanRun> Layout::ShapeScanlineMaker::makeScanline(Layout::LineHeight const &line_height)
 
115
{
 
116
    FloatLigne line_rasterization;
 
117
    FloatLigne line_decent_length_runs;
 
118
    float line_text_height = (float)(line_height.ascent + line_height.descent);
 
119
 
 
120
    if (_y > _bounding_box_bottom)
 
121
        return std::vector<ScanRun>();
 
122
 
 
123
    if (_y < _bounding_box_top)
 
124
        _y = _bounding_box_top;
 
125
 
 
126
    if (line_text_height == 0.0)
 
127
        line_text_height = 0.001;     // Scan() doesn't work for zero height so this will have to do
 
128
 
 
129
    _current_line_height = (float)line_height.total();
 
130
 
 
131
    // I think what's going on here is that we're moving the top of the scanline to the given position...
 
132
    _rotated_shape->Scan(_rasterizer_y, _current_rasterization_point, _y, line_text_height);
 
133
    // ...then actually retreiving the scanline (which alters the first two parameters)
 
134
    _rotated_shape->Scan(_rasterizer_y, _current_rasterization_point, _y + line_text_height , &line_rasterization, true, line_text_height);
 
135
    // sanitise the raw rasterisation, which could have weird overlaps
 
136
    line_rasterization.Flatten();
 
137
    // cut out runs that cover less than 90% of the line
 
138
    line_decent_length_runs.Over(&line_rasterization, 0.9 * line_text_height);
 
139
 
 
140
    if (line_decent_length_runs.runs.empty())
 
141
    {
 
142
        if (line_rasterization.runs.empty())
 
143
            return std::vector<ScanRun>();     // stop the flow
 
144
        // make up a pointless run: anything that's not an empty vector
 
145
        std::vector<ScanRun> result(1);
 
146
        result[0].x_start = line_rasterization.runs[0].st;
 
147
        result[0].x_end   = line_rasterization.runs[0].st;
 
148
        result[0].y = _negative_block_progression ? -_current_line_height - _y : _y;
 
149
        return result;
 
150
    }
 
151
 
 
152
    // convert the FloatLigne to what we use: vector<ScanRun>
 
153
    std::vector<ScanRun> result(line_decent_length_runs.runs.size());
 
154
    for (unsigned i = 0 ; i < result.size() ; i++) {
 
155
        result[i].x_start = line_decent_length_runs.runs[i].st;
 
156
        result[i].x_end   = line_decent_length_runs.runs[i].en;
 
157
        result[i].y = _negative_block_progression ? -_current_line_height - _y : _y;
 
158
    }
 
159
 
 
160
    return result;
 
161
}
 
162
 
 
163
void Layout::ShapeScanlineMaker::completeLine()
 
164
{
 
165
    _y += _current_line_height;
 
166
}
 
167
 
 
168
double Layout::ShapeScanlineMaker::yCoordinate()
 
169
{
 
170
    if (_negative_block_progression) return -_current_line_height - _y;
 
171
    return _y;
 
172
}
 
173
 
 
174
void Layout::ShapeScanlineMaker::setNewYCoordinate(double new_y)
 
175
{
 
176
    _y = (float)new_y;
 
177
    if (_negative_block_progression) _y = -_current_line_height - _y;
 
178
    // what will happen with the rasteriser if we move off the shape?
 
179
    // it's not an important question because <flowSpan> doesn't have a y attribute
 
180
}
 
181
 
 
182
bool Layout::ShapeScanlineMaker::canExtendCurrentScanline(Layout::LineHeight const &/*line_height*/)
 
183
{
 
184
    //we actually could return true if only the leading changed, but that's too much effort for something that rarely happens
 
185
    return false;
 
186
}
 
187
 
 
188
}//namespace Text
 
189
}//namespace Inkscape