Coverage Report

Created: 2026-02-14 06:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/tesseract/src/ccstruct/ocrrow.cpp
Line
Count
Source
1
/**********************************************************************
2
 * File:        ocrrow.cpp  (Formerly row.c)
3
 * Description: Code for the ROW class.
4
 * Author:      Ray Smith
5
 *
6
 * (C) Copyright 1991, Hewlett-Packard Ltd.
7
 ** Licensed under the Apache License, Version 2.0 (the "License");
8
 ** you may not use this file except in compliance with the License.
9
 ** You may obtain a copy of the License at
10
 ** http://www.apache.org/licenses/LICENSE-2.0
11
 ** Unless required by applicable law or agreed to in writing, software
12
 ** distributed under the License is distributed on an "AS IS" BASIS,
13
 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 ** See the License for the specific language governing permissions and
15
 ** limitations under the License.
16
 *
17
 **********************************************************************/
18
19
// Include automatically generated configuration file if running autoconf.
20
#ifdef HAVE_CONFIG_H
21
#  include "config_auto.h"
22
#endif
23
24
#include "blobbox.h"
25
#include "ocrrow.h"
26
27
namespace tesseract {
28
29
/**********************************************************************
30
 * ROW::ROW
31
 *
32
 * Constructor to build a ROW. Only the stats stuff are given here.
33
 * The words are added directly.
34
 **********************************************************************/
35
ROW::ROW(                // constructor
36
    int32_t spline_size, // no of segments
37
    int32_t *xstarts,    // segment boundaries
38
    double *coeffs,      // coefficients
39
    float x_height,      // line height
40
    float ascenders,     // ascender size
41
    float descenders,    // descender drop
42
    int16_t kern,        // char gap
43
    int16_t space        // word gap
44
    )
45
0
    : baseline(spline_size, xstarts, coeffs), para_(nullptr) {
46
0
  kerning = kern; // just store stuff
47
0
  spacing = space;
48
0
  xheight = x_height;
49
0
  ascrise = ascenders;
50
0
  bodysize = 0.0f;
51
0
  descdrop = descenders;
52
0
  has_drop_cap_ = false;
53
0
  lmargin_ = 0;
54
0
  rmargin_ = 0;
55
0
}
56
57
/**********************************************************************
58
 * ROW::ROW
59
 *
60
 * Constructor to build a ROW. Only the stats stuff are given here.
61
 * The words are added directly.
62
 **********************************************************************/
63
64
ROW::ROW(           // constructor
65
    TO_ROW *to_row, // source row
66
    int16_t kern,   // char gap
67
    int16_t space   // word gap
68
    )
69
171k
    : para_(nullptr) {
70
171k
  kerning = kern; // just store stuff
71
171k
  spacing = space;
72
171k
  xheight = to_row->xheight;
73
171k
  bodysize = to_row->body_size;
74
171k
  ascrise = to_row->ascrise;
75
171k
  descdrop = to_row->descdrop;
76
171k
  baseline = to_row->baseline;
77
171k
  has_drop_cap_ = false;
78
171k
  lmargin_ = 0;
79
171k
  rmargin_ = 0;
80
171k
}
81
82
// Returns the bounding box including the desired combination of upper and
83
// lower noise/diacritic elements.
84
0
TBOX ROW::restricted_bounding_box(bool upper_dots, bool lower_dots) const {
85
0
  TBOX box;
86
  // This is a read-only iteration of the words in the row.
87
0
  WERD_IT it(const_cast<WERD_LIST *>(&words));
88
0
  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
89
0
    box += it.data()->restricted_bounding_box(upper_dots, lower_dots);
90
0
  }
91
0
  return box;
92
0
}
93
94
/**********************************************************************
95
 * ROW::recalc_bounding_box
96
 *
97
 * Set the bounding box correctly
98
 **********************************************************************/
99
100
171k
void ROW::recalc_bounding_box() { // recalculate BB
101
171k
  WERD *word;                     // current word
102
171k
  WERD_IT it = &words;            // words of ROW
103
171k
  int16_t left;                   // of word
104
171k
  int16_t prev_left;              // old left
105
106
171k
  if (!it.empty()) {
107
171k
    word = it.data();
108
171k
    prev_left = word->bounding_box().left();
109
171k
    it.forward();
110
266k
    while (!it.at_first()) {
111
95.3k
      word = it.data();
112
95.3k
      left = word->bounding_box().left();
113
95.3k
      if (left < prev_left) {
114
0
        it.move_to_first();
115
        // words in BB order
116
0
        it.sort(word_comparator);
117
0
        break;
118
0
      }
119
95.3k
      prev_left = left;
120
95.3k
      it.forward();
121
95.3k
    }
122
171k
  }
123
437k
  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
124
266k
    word = it.data();
125
266k
    if (it.at_first()) {
126
171k
      word->set_flag(W_BOL, true);
127
171k
    } else {
128
      // not start of line
129
95.3k
      word->set_flag(W_BOL, false);
130
95.3k
    }
131
266k
    if (it.at_last()) {
132
171k
      word->set_flag(W_EOL, true);
133
171k
    } else {
134
      // not end of line
135
95.3k
      word->set_flag(W_EOL, false);
136
95.3k
    }
137
    // extend BB as reqd
138
266k
    bound_box += word->bounding_box();
139
266k
  }
140
171k
}
141
142
/**********************************************************************
143
 * ROW::move
144
 *
145
 * Reposition row by vector
146
 **********************************************************************/
147
148
void ROW::move(      // reposition row
149
    const ICOORD vec // by vector
150
0
) {
151
0
  WERD_IT it(&words); // word iterator
152
153
0
  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
154
0
    it.data()->move(vec);
155
0
  }
156
157
0
  bound_box.move(vec);
158
0
  baseline.move(vec);
159
0
}
160
161
/**********************************************************************
162
 * ROW::print
163
 *
164
 * Display members
165
 **********************************************************************/
166
167
void ROW::print( // print
168
    FILE *fp     // file to print on
169
0
) const {
170
0
  tprintf("Kerning= %d\n", kerning);
171
0
  tprintf("Spacing= %d\n", spacing);
172
0
  bound_box.print();
173
0
  tprintf("Xheight= %f\n", xheight);
174
0
  tprintf("Ascrise= %f\n", ascrise);
175
0
  tprintf("Descdrop= %f\n", descdrop);
176
0
  tprintf("has_drop_cap= %d\n", has_drop_cap_);
177
0
  tprintf("lmargin= %d, rmargin= %d\n", lmargin_, rmargin_);
178
0
}
179
180
/**********************************************************************
181
 * ROW::plot
182
 *
183
 * Draw the ROW in the given colour.
184
 **********************************************************************/
185
186
#ifndef GRAPHICS_DISABLED
187
void ROW::plot(              // draw it
188
    ScrollView *window,      // window to draw in
189
    ScrollView::Color colour // colour to draw in
190
) {
191
  WERD *word;          // current word
192
  WERD_IT it = &words; // words of ROW
193
194
  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
195
    word = it.data();
196
    word->plot(window, colour); // all in one colour
197
  }
198
}
199
200
/**********************************************************************
201
 * ROW::plot
202
 *
203
 * Draw the ROW in rainbow colours.
204
 **********************************************************************/
205
206
void ROW::plot(        // draw it
207
    ScrollView *window // window to draw in
208
) {
209
  WERD *word;          // current word
210
  WERD_IT it = &words; // words of ROW
211
212
  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
213
    word = it.data();
214
    word->plot(window); // in rainbow colours
215
  }
216
}
217
#endif // !GRAPHICS_DISABLED
218
219
/**********************************************************************
220
 * ROW::operator=
221
 *
222
 * Assign rows by duplicating the row structure but NOT the WERDLIST
223
 **********************************************************************/
224
225
0
ROW &ROW::operator=(const ROW &source) {
226
0
  this->ELIST<ROW>::LINK::operator=(source);
227
0
  kerning = source.kerning;
228
0
  spacing = source.spacing;
229
0
  xheight = source.xheight;
230
0
  bodysize = source.bodysize;
231
0
  ascrise = source.ascrise;
232
0
  descdrop = source.descdrop;
233
0
  if (!words.empty()) {
234
0
    words.clear();
235
0
  }
236
0
  baseline = source.baseline; // QSPLINES must do =
237
0
  bound_box = source.bound_box;
238
0
  has_drop_cap_ = source.has_drop_cap_;
239
0
  lmargin_ = source.lmargin_;
240
0
  rmargin_ = source.rmargin_;
241
0
  para_ = source.para_;
242
0
  return *this;
243
0
}
244
245
} // namespace tesseract