44 for (
int r = 0; r < results.
size(); ++r) {
45 const int shape_id = results[r].shape_id;
61 for (
int r = 0; r < results.
size(); ++r) {
80 const auto* p1 = static_cast<const UnicharAndFonts*>(v1);
81 const auto* p2 = static_cast<const UnicharAndFonts*>(v2);
82 return p1->unichar_id - p2->unichar_id;
87 uint8_t sorted = unichars_sorted_;
95 unichars_sorted_ = sorted != 0;
96 return unichars_.DeSerializeClasses(fp);
102 for (
int c = 0; c < unichars_.size(); ++c) {
103 if (unichars_[c].unichar_id == unichar_id) {
106 for (
int f = 0; f < font_list.
size(); ++f) {
107 if (font_list[f] == font_id)
116 unichars_sorted_ = unichars_.size() <= 1;
121 for (
int c = 0; c < other.unichars_.size(); ++c) {
122 for (
int f = 0; f < other.unichars_[c].font_ids.size(); ++f) {
124 other.unichars_[c].font_ids[f]);
127 unichars_sorted_ = unichars_.size() <= 1;
132 for (
int c = 0; c < unichars_.size(); ++c) {
133 if (unichars_[c].unichar_id == unichar_id) {
136 for (
int f = 0; f < font_list.
size(); ++f) {
137 if (font_list[f] == font_id)
148 for (
int c = 0; c < unichars_.size(); ++c) {
149 if (unichars_[c].unichar_id == unichar_id) {
158 for (
int c = 0; c < unichars_.size(); ++c) {
160 for (
int f = 0; f < font_list.
size(); ++f) {
161 if (font_list[f] == font_id)
170 uint32_t properties)
const {
171 for (
int c = 0; c < unichars_.size(); ++c) {
173 for (
int f = 0; f < font_list.
size(); ++f) {
174 if (font_table.
get(font_list[f]).properties == properties)
184 uint32_t properties = font_table.
get(unichars_[0].font_ids[0]).properties;
185 for (
int c = 0; c < unichars_.size(); ++c) {
187 for (
int f = 0; f < font_list.
size(); ++f) {
188 if (font_table.
get(font_list[f]).properties != properties)
203 for (
int c = 0; c < unichars_.size(); ++c) {
204 int unichar_id = unichars_[c].unichar_id;
206 for (
int f = 0; f < font_list.
size(); ++f) {
218 if (unichars_.size() != other->unichars_.size())
return false;
219 if (!unichars_sorted_) SortUnichars();
220 if (!other->unichars_sorted_) other->SortUnichars();
221 for (
int c = 0; c < unichars_.size(); ++c) {
222 if (unichars_[c].unichar_id != other->unichars_[c].unichar_id)
229 void Shape::SortUnichars() {
231 unichars_sorted_ =
true;
242 return shape_table_.Serialize(fp);
247 if (!shape_table_.DeSerialize(fp))
return false;
255 if (num_fonts_ <= 0) {
256 for (
int shape_id = 0; shape_id < shape_table_.size(); ++shape_id) {
257 const Shape& shape = *shape_table_[shape_id];
258 for (
int c = 0; c < shape.
size(); ++c) {
259 for (
int f = 0; f < shape[c].font_ids.
size(); ++f) {
260 if (shape[c].font_ids[f] >= num_fonts_)
261 num_fonts_ = shape[c].font_ids[f] + 1;
272 for (
int shape_id = 0; shape_id < shape_table_.size(); ++shape_id) {
273 Shape* shape = shape_table_[shape_id];
274 for (
int c = 0; c < shape->
size(); ++c) {
275 shape->
SetUnicharId(c, unicharset_map[(*shape)[c].unichar_id]);
282 if (shape_id < 0 || shape_id >= shape_table_.size())
283 return STRING(
"INVALID_UNICHAR_ID");
287 if (shape.
size() > 100) {
291 for (
int c = 0; c < shape.
size(); ++c) {
295 if (shape.
size() < 10) {
297 result +=
" fonts =";
298 int num_fonts = shape[c].font_ids.
size();
299 if (num_fonts > 10) {
301 result.
add_str_int(
" ... ", shape[c].font_ids[num_fonts - 1]);
303 for (
int f = 0; f < num_fonts; ++f) {
314 int max_unichars = 0;
315 int num_multi_shapes = 0;
316 int num_master_shapes = 0;
317 for (
int s = 0; s < shape_table_.size(); ++s) {
323 if (shape_size > max_unichars)
324 max_unichars = shape_size;
327 result.
add_str_int(
"Number of shapes = ", num_master_shapes);
328 result.
add_str_int(
" max unichars = ", max_unichars);
329 result.
add_str_int(
" number with multiple unichars = ", num_multi_shapes);
337 int index = shape_table_.size();
338 auto* shape =
new Shape;
340 shape_table_.push_back(shape);
341 num_fonts_ = std::max(num_fonts_, font_id + 1);
349 for (index = 0; index < shape_table_.size() &&
350 !(other == *shape_table_[index]); ++index)
352 if (index == shape_table_.size()) {
353 auto* shape =
new Shape(other);
354 shape_table_.push_back(shape);
362 delete shape_table_[shape_id];
363 shape_table_[shape_id] =
nullptr;
364 shape_table_.remove(shape_id);
370 Shape& shape = *shape_table_[shape_id];
372 num_fonts_ = std::max(num_fonts_, font_id + 1);
377 Shape& shape = *shape_table_[shape_id];
387 for (
int s = 0; s < shape_table_.size(); ++s) {
389 for (
int c = 0; c < shape.
size(); ++c) {
390 if (shape[c].unichar_id == unichar_id) {
393 for (
int f = 0; f < shape[c].font_ids.
size(); ++f) {
394 if (shape[c].font_ids[f] == font_id)
405 int* unichar_id,
int* font_id)
const {
406 const UnicharAndFonts& unichar_and_fonts = (*shape_table_[shape_id])[0];
408 *font_id = unichar_and_fonts.
font_ids[0];
416 for (
int u_ind = 0; u_ind < shape.
size(); ++u_ind) {
417 for (
int f_ind = 0; f_ind < shape[u_ind].font_ids.
size(); ++f_ind) {
418 int c = shape[u_ind].unichar_id;
419 int f = shape[u_ind].font_ids[f_ind];
420 int master_id = master_shapes.
FindShape(c, f);
421 if (master_id >= 0) {
422 shape_map.SetBit(master_id);
429 for (
int s = 0; s < master_shapes.
NumShapes(); ++s) {
446 for (
int s1 = 0; s1 < num_shapes; ++s1) {
456 int max_num_unichars = 0;
458 for (
int s = 0; s < num_shapes; ++s) {
459 if (
GetShape(s).size() > max_num_unichars)
462 return max_num_unichars;
469 for (
int s1 = start; s1 < end; ++s1) {
471 int unichar_id =
GetShape(s1)[0].unichar_id;
472 for (
int s2 = s1 + 1; s2 < end; ++s2) {
474 unichar_id ==
GetShape(s2)[0].unichar_id) {
496 for (
int c = 0; c < shape.
size(); ++c) {
497 font_count += shape[c].font_ids.
size();
507 Shape combined_shape(*shape_table_[master_id1]);
508 combined_shape.
AddShape(*shape_table_[master_id2]);
509 return combined_shape.
size();
517 shape_table_[master_id2]->set_destination_index(master_id1);
519 shape_table_[master_id1]->AddShape(*shape_table_[master_id2]);
524 Shape* tmp = shape_table_[shape_id1];
525 shape_table_[shape_id1] = shape_table_[shape_id2];
526 shape_table_[shape_id2] = tmp;
532 int dest_id = shape_table_[shape_id]->destination_index();
533 if (dest_id == shape_id || dest_id < 0)
535 int master_id = shape_table_[dest_id]->destination_index();
536 if (master_id == dest_id || master_id < 0)
547 for (c1 = 0; c1 < shape1.
size(); ++c1) {
548 int unichar_id1 = shape1[c1].unichar_id;
552 for (c2 = 0; c2 < shape2.
size(); ++c2) {
553 int unichar_id2 = shape2[c2].unichar_id;
557 return c1 == shape1.
size() || c2 == shape2.
size();
562 int shape_id)
const {
567 for (cs = 0; cs < shape.
size(); ++cs) {
568 int unichar_id = shape[cs].unichar_id;
573 for (cm1 = 0; cm1 < merge1.
size(); ++cm1) {
574 int unichar_id1 = merge1[cm1].unichar_id;
578 for (cm2 = 0; cm2 < merge2.
size(); ++cm2) {
579 int unichar_id2 = merge2[cm2].unichar_id;
583 return cs == shape.
size() || (cm1 == merge1.
size() && cm2 == merge2.
size());
590 for (
int c1 = 0; c1 < shape1.
size(); ++c1) {
591 int unichar_id1 = shape1[c1].unichar_id;
595 for (
int c2 = 0; c2 < shape2.
size(); ++c2) {
596 int unichar_id2 = shape2[c2].unichar_id;
605 int shape_id)
const {
609 for (
int cs = 0; cs < shape.
size(); ++cs) {
610 int unichar_id = shape[cs].unichar_id;
615 for (
int cm1 = 0; cm1 < merge1.
size(); ++cm1) {
616 int unichar_id1 = merge1[cm1].unichar_id;
620 for (
int cm2 = 0; cm2 < merge2.
size(); ++cm2) {
621 int unichar_id2 = merge2[cm2].unichar_id;
632 for (
int c1 = 0; c1 < shape1.
size(); ++c1) {
633 int unichar_id1 = shape1[c1].unichar_id;
644 for (
int c1 = 0; c1 < shape1.
size(); ++c1) {
646 for (
int f = 0; f < font_list1.
size(); ++f) {
658 if (shape_map !=
nullptr)
660 for (
int s = 0; s < other.shape_table_.size(); ++s) {
661 if (other.shape_table_[s]->destination_index() < 0) {
662 int index =
AddShape(*other.shape_table_[s]);
663 if (shape_map !=
nullptr)
664 (*shape_map)[s] = index;
672 for (
int s = 0; s < shape_table_.size(); ++s) {
673 if (shape_table_[s]->destination_index() < 0)
690 if (shape_rating.
joined) {
694 if (shape_rating.
broken) {
699 for (
int u = 0; u < shape.
size(); ++u) {
700 int result_index = AddUnicharToResults(shape[u].unichar_id,
702 unichar_map, results);
703 for (
int f = 0; f < shape[u].font_ids.
size(); ++f) {
704 (*results)[result_index].fonts.push_back(
713 int ShapeTable::AddUnicharToResults(
716 int result_index = unichar_map->
get(unichar_id);
717 if (result_index < 0) {
719 result_index = results->
push_back(result);
720 (*unichar_map)[unichar_id] = result_index;