Coverage Report

Created: 2025-06-13 07:15

/src/tesseract/src/ccstruct/fontinfo.cpp
Line
Count
Source (jump to first uncovered line)
1
///////////////////////////////////////////////////////////////////////
2
// File:        fontinfo.cpp
3
// Description: Font information classes abstracted from intproto.h/cpp.
4
// Author:      rays@google.com (Ray Smith)
5
//
6
// (C) Copyright 2011, Google Inc.
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 "fontinfo.h"
20
#include "bitvector.h"
21
#include "unicity_table.h"
22
23
namespace tesseract {
24
25
// Writes to the given file. Returns false in case of error.
26
0
bool FontInfo::Serialize(FILE *fp) const {
27
0
  if (!write_info(fp, *this)) {
28
0
    return false;
29
0
  }
30
0
  if (!write_spacing_info(fp, *this)) {
31
0
    return false;
32
0
  }
33
0
  return true;
34
0
}
35
// Reads from the given file. Returns false in case of error.
36
// If swap is true, assumes a big/little-endian swap is needed.
37
0
bool FontInfo::DeSerialize(TFile *fp) {
38
0
  if (!read_info(fp, this)) {
39
0
    return false;
40
0
  }
41
0
  if (!read_spacing_info(fp, this)) {
42
0
    return false;
43
0
  }
44
0
  return true;
45
0
}
46
47
0
FontInfoTable::FontInfoTable() {
48
0
  using namespace std::placeholders; // for _1, _2
49
0
  set_clear_callback(std::bind(FontInfoDeleteCallback, _1));
50
0
}
51
52
0
FontInfoTable::~FontInfoTable() = default;
53
54
// Writes to the given file. Returns false in case of error.
55
0
bool FontInfoTable::Serialize(FILE *fp) const {
56
0
  return this->SerializeClasses(fp);
57
0
}
58
// Reads from the given file. Returns false in case of error.
59
// If swap is true, assumes a big/little-endian swap is needed.
60
0
bool FontInfoTable::DeSerialize(TFile *fp) {
61
0
  truncate(0);
62
0
  return this->DeSerializeClasses(fp);
63
0
}
64
65
// Returns true if the given set of fonts includes one with the same
66
// properties as font_id.
67
bool FontInfoTable::SetContainsFontProperties(int font_id,
68
0
                                              const std::vector<ScoredFont> &font_set) const {
69
0
  uint32_t properties = at(font_id).properties;
70
0
  for (auto &&f : font_set) {
71
0
    if (at(f.fontinfo_id).properties == properties) {
72
0
      return true;
73
0
    }
74
0
  }
75
0
  return false;
76
0
}
77
78
// Returns true if the given set of fonts includes multiple properties.
79
bool FontInfoTable::SetContainsMultipleFontProperties(
80
0
    const std::vector<ScoredFont> &font_set) const {
81
0
  if (font_set.empty()) {
82
0
    return false;
83
0
  }
84
0
  int first_font = font_set[0].fontinfo_id;
85
0
  uint32_t properties = at(first_font).properties;
86
0
  for (unsigned f = 1; f < font_set.size(); ++f) {
87
0
    if (at(font_set[f].fontinfo_id).properties != properties) {
88
0
      return true;
89
0
    }
90
0
  }
91
0
  return false;
92
0
}
93
94
// Moves any non-empty FontSpacingInfo entries from other to this.
95
0
void FontInfoTable::MoveSpacingInfoFrom(FontInfoTable *other) {
96
0
  using namespace std::placeholders; // for _1, _2
97
0
  set_clear_callback(std::bind(FontInfoDeleteCallback, _1));
98
0
  for (unsigned i = 0; i < other->size(); ++i) {
99
0
    std::vector<FontSpacingInfo *> *spacing_vec = other->at(i).spacing_vec;
100
0
    if (spacing_vec != nullptr) {
101
0
      int target_index = get_index(other->at(i));
102
0
      if (target_index < 0) {
103
        // Bit copy the FontInfo and steal all the pointers.
104
0
        push_back(other->at(i));
105
0
        other->at(i).name = nullptr;
106
0
      } else {
107
0
        delete at(target_index).spacing_vec;
108
0
        at(target_index).spacing_vec = other->at(i).spacing_vec;
109
0
      }
110
0
      other->at(i).spacing_vec = nullptr;
111
0
    }
112
0
  }
113
0
}
114
115
// Moves this to the target unicity table.
116
0
void FontInfoTable::MoveTo(UnicityTable<FontInfo> *target) {
117
0
  target->clear();
118
0
  using namespace std::placeholders; // for _1, _2
119
0
  target->set_clear_callback(std::bind(FontInfoDeleteCallback, _1));
120
0
  for (unsigned i = 0; i < size(); ++i) {
121
    // Bit copy the FontInfo and steal all the pointers.
122
0
    target->push_back(at(i));
123
0
    at(i).name = nullptr;
124
0
    at(i).spacing_vec = nullptr;
125
0
  }
126
0
}
127
128
// Callbacks for GenericVector.
129
0
void FontInfoDeleteCallback(FontInfo f) {
130
0
  if (f.spacing_vec != nullptr) {
131
0
    for (auto data : *f.spacing_vec) {
132
0
      delete data;
133
0
    }
134
0
    delete f.spacing_vec;
135
0
    f.spacing_vec = nullptr;
136
0
  }
137
0
  delete[] f.name;
138
0
  f.name = nullptr;
139
0
}
140
141
/*---------------------------------------------------------------------------*/
142
// Callbacks used by UnicityTable to read/write FontInfo/FontSet structures.
143
1.70k
bool read_info(TFile *f, FontInfo *fi) {
144
1.70k
  uint32_t size;
145
1.70k
  if (!f->DeSerialize(&size)) {
146
0
    return false;
147
0
  }
148
1.70k
  char *font_name = new char[size + 1];
149
1.70k
  fi->name = font_name;
150
1.70k
  if (!f->DeSerialize(font_name, size)) {
151
0
    return false;
152
0
  }
153
1.70k
  font_name[size] = '\0';
154
1.70k
  return f->DeSerialize(&fi->properties);
155
1.70k
}
156
157
0
bool write_info(FILE *f, const FontInfo &fi) {
158
0
  int32_t size = strlen(fi.name);
159
0
  return tesseract::Serialize(f, &size) && tesseract::Serialize(f, &fi.name[0], size) &&
160
0
         tesseract::Serialize(f, &fi.properties);
161
0
}
162
163
1.70k
bool read_spacing_info(TFile *f, FontInfo *fi) {
164
1.70k
  int32_t vec_size, kern_size;
165
1.70k
  if (!f->DeSerialize(&vec_size)) {
166
0
    return false;
167
0
  }
168
1.70k
  ASSERT_HOST(vec_size >= 0);
169
1.70k
  if (vec_size == 0) {
170
1.58k
    return true;
171
1.58k
  }
172
128
  fi->init_spacing(vec_size);
173
14.5k
  for (int i = 0; i < vec_size; ++i) {
174
14.4k
    auto *fs = new FontSpacingInfo();
175
14.4k
    if (!f->DeSerialize(&fs->x_gap_before) || !f->DeSerialize(&fs->x_gap_after) ||
176
14.4k
        !f->DeSerialize(&kern_size)) {
177
0
      delete fs;
178
0
      return false;
179
0
    }
180
14.4k
    if (kern_size < 0) { // indication of a nullptr entry in fi->spacing_vec
181
2.56k
      delete fs;
182
2.56k
      continue;
183
2.56k
    }
184
11.9k
    if (kern_size > 0 &&
185
11.9k
        (!f->DeSerialize(fs->kerned_unichar_ids) || !f->DeSerialize(fs->kerned_x_gaps))) {
186
0
      delete fs;
187
0
      return false;
188
0
    }
189
11.9k
    fi->add_spacing(i, fs);
190
11.9k
  }
191
128
  return true;
192
128
}
193
194
0
bool write_spacing_info(FILE *f, const FontInfo &fi) {
195
0
  int32_t vec_size = (fi.spacing_vec == nullptr) ? 0 : fi.spacing_vec->size();
196
0
  if (!tesseract::Serialize(f, &vec_size)) {
197
0
    return false;
198
0
  }
199
0
  int16_t x_gap_invalid = -1;
200
0
  for (int i = 0; i < vec_size; ++i) {
201
0
    FontSpacingInfo *fs = fi.spacing_vec->at(i);
202
0
    int32_t kern_size = (fs == nullptr) ? -1 : fs->kerned_x_gaps.size();
203
0
    if (fs == nullptr) {
204
      // Writing two invalid x-gaps.
205
0
      if (!tesseract::Serialize(f, &x_gap_invalid, 2) || !tesseract::Serialize(f, &kern_size)) {
206
0
        return false;
207
0
      }
208
0
    } else {
209
0
      if (!tesseract::Serialize(f, &fs->x_gap_before) ||
210
0
          !tesseract::Serialize(f, &fs->x_gap_after) || !tesseract::Serialize(f, &kern_size)) {
211
0
        return false;
212
0
      }
213
0
    }
214
0
    if (kern_size > 0 &&
215
0
        (!Serialize(f, fs->kerned_unichar_ids) || !Serialize(f, fs->kerned_x_gaps))) {
216
0
      return false;
217
0
    }
218
0
  }
219
0
  return true;
220
0
}
221
222
0
bool write_set(FILE *f, const FontSet &fs) {
223
0
  int size = fs.size();
224
0
  return tesseract::Serialize(f, &size) &&
225
0
         (size > 0 ? tesseract::Serialize(f, &fs[0], size) : true);
226
0
}
227
228
} // namespace tesseract.