Coverage Report

Created: 2026-10-28 06:29

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
180k
    : para_(nullptr) {
70
180k
  kerning = kern; // just store stuff
71
180k
  spacing = space;
72
180k
  xheight = to_row->xheight;
73
180k
  bodysize = to_row->body_size;
74
180k
  ascrise = to_row->ascrise;
75
180k
  descdrop = to_row->descdrop;
76
180k
  baseline = to_row->baseline;
77
180k
  has_drop_cap_ = false;
78
180k
  lmargin_ = 0;
79
180k
  rmargin_ = 0;
80
180k
}
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
180k
void ROW::recalc_bounding_box() { // recalculate BB
101
180k
  WERD *word;                     // current word
102
180k
  WERD_IT it = &words;            // words of ROW
103
180k
  int16_t left;                   // of word
104
180k
  int16_t prev_left;              // old left
105
106
180k
  if (!it.empty()) {
107
180k
    word = it.data();
108
180k
    prev_left = word->bounding_box().left();
109
180k
    it.forward();
110
301k
    while (!it.at_first()) {
111
121k
      word = it.data();
112
121k
      left = word->bounding_box().left();
113
121k
      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
121k
      prev_left = left;
120
121k
      it.forward();
121
121k
    }
122
180k
  }
123
481k
  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
124
301k
    word = it.data();
125
301k
    if (it.at_first()) {
126
180k
      word->set_flag(W_BOL, true);
127
180k
    } else {
128
      // not start of line
129
121k
      word->set_flag(W_BOL, false);
130
121k
    }
131
301k
    if (it.at_last()) {
132
180k
      word->set_flag(W_EOL, true);
133
180k
    } else {
134
      // not end of line
135
121k
      word->set_flag(W_EOL, false);
136
121k
    }
137
    // extend BB as reqd
138
301k
    bound_box += word->bounding_box();
139
301k
  }
140
180k
}
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
0
void ROW::print() const {
168
0
  tprintf("Kerning= %d\n", kerning);
169
0
  tprintf("Spacing= %d\n", spacing);
170
0
  bound_box.print();
171
0
  tprintf("Xheight= %f\n", xheight);
172
0
  tprintf("Ascrise= %f\n", ascrise);
173
0
  tprintf("Descdrop= %f\n", descdrop);
174
0
  tprintf("has_drop_cap= %d\n", has_drop_cap_);
175
0
  tprintf("lmargin= %d, rmargin= %d\n", lmargin_, rmargin_);
176
0
}
177
178
/**********************************************************************
179
 * ROW::plot
180
 *
181
 * Draw the ROW in the given colour.
182
 **********************************************************************/
183
184
#ifndef GRAPHICS_DISABLED
185
void ROW::plot(              // draw it
186
    ScrollView *window,      // window to draw in
187
    ScrollView::Color colour // colour to draw in
188
) {
189
  WERD *word;          // current word
190
  WERD_IT it = &words; // words of ROW
191
192
  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
193
    word = it.data();
194
    word->plot(window, colour); // all in one colour
195
  }
196
}
197
198
/**********************************************************************
199
 * ROW::plot
200
 *
201
 * Draw the ROW in rainbow colours.
202
 **********************************************************************/
203
204
void ROW::plot(        // draw it
205
    ScrollView *window // window to draw in
206
) {
207
  WERD *word;          // current word
208
  WERD_IT it = &words; // words of ROW
209
210
  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
211
    word = it.data();
212
    word->plot(window); // in rainbow colours
213
  }
214
}
215
#endif // !GRAPHICS_DISABLED
216
217
/**********************************************************************
218
 * ROW::operator=
219
 *
220
 * Assign rows by duplicating the row structure but NOT the WERDLIST
221
 **********************************************************************/
222
223
0
ROW &ROW::operator=(const ROW &source) {
224
0
  this->ELIST<ROW>::LINK::operator=(source);
225
0
  kerning = source.kerning;
226
0
  spacing = source.spacing;
227
0
  xheight = source.xheight;
228
0
  bodysize = source.bodysize;
229
0
  ascrise = source.ascrise;
230
0
  descdrop = source.descdrop;
231
0
  if (!words.empty()) {
232
0
    words.clear();
233
0
  }
234
0
  baseline = source.baseline; // QSPLINES must do =
235
0
  bound_box = source.bound_box;
236
0
  has_drop_cap_ = source.has_drop_cap_;
237
0
  lmargin_ = source.lmargin_;
238
0
  rmargin_ = source.rmargin_;
239
0
  para_ = source.para_;
240
0
  return *this;
241
0
}
242
243
} // namespace tesseract