864 {
866 C_BLOB *blob;
867 WERD *word;
868 int32_t blob_count;
869 int32_t src_index;
870 int32_t dest_index;
871 float ydiff;
872 float x_centre;
873
874 WERD_IT word_it = row->word_list();
875 C_BLOB_IT blob_it;
876
877 blob_count = 0;
878 for (word_it.mark_cycle_pt(); !word_it.cycled_list(); word_it.forward()) {
879 word = word_it.data();
880
881 blob_count += word->cblob_list()->length();
882 }
883 if (blob_count == 0) {
884 return;
885 }
886
887 std::vector<int32_t> xstarts(blob_count + row->baseline.segments + 1);
888
889 std::vector<double> coeffs((blob_count + row->baseline.segments) * 3);
890
891 src_index = 0;
892 dest_index = 0;
893 xstarts[0] = row->baseline.xcoords[0];
894 for (word_it.mark_cycle_pt(); !word_it.cycled_list(); word_it.forward()) {
895 word = word_it.data();
896
897 blob_it.set_to_list(word->cblob_list());
898 for (blob_it.mark_cycle_pt(); !blob_it.cycled_list(); blob_it.forward()) {
899 blob = blob_it.data();
900 blob_box = blob->bounding_box();
901 x_centre = (blob_box.left() + blob_box.right()) / 2.0;
902 ydiff = blob_box.bottom() - row->base_line(x_centre);
903 if (ydiff < 0) {
904 ydiff = -ydiff / row->x_height();
905 } else {
906 ydiff = ydiff / row->x_height();
907 }
908 if (ydiff < blshift_maxshift && blob_box.height() / row->x_height() > blshift_xfraction) {
909 if (xstarts[dest_index] >= x_centre) {
910 xstarts[dest_index] = blob_box.left();
911 }
912 coeffs[dest_index * 3] = 0;
913 coeffs[dest_index * 3 + 1] = 0;
914 coeffs[dest_index * 3 + 2] = blob_box.bottom();
915
916 dest_index++;
917 xstarts[dest_index] = blob_box.right() + 1;
918 } else {
919 if (xstarts[dest_index] <= x_centre) {
920 while (row->baseline.xcoords[src_index + 1] <= x_centre &&
921 src_index < row->baseline.segments - 1) {
922 if (row->baseline.xcoords[src_index + 1] > xstarts[dest_index]) {
923 coeffs[dest_index * 3] = row->baseline.quadratics[src_index].a;
924 coeffs[dest_index * 3 + 1] = row->baseline.quadratics[src_index].b;
925 coeffs[dest_index * 3 + 2] = row->baseline.quadratics[src_index].c;
926 dest_index++;
927 xstarts[dest_index] = row->baseline.xcoords[src_index + 1];
928 }
929 src_index++;
930 }
931 coeffs[dest_index * 3] = row->baseline.quadratics[src_index].a;
932 coeffs[dest_index * 3 + 1] = row->baseline.quadratics[src_index].b;
933 coeffs[dest_index * 3 + 2] = row->baseline.quadratics[src_index].c;
934 dest_index++;
935 xstarts[dest_index] = row->baseline.xcoords[src_index + 1];
936 }
937 }
938 }
939 }
940 while (src_index < row->baseline.segments &&
941 row->baseline.xcoords[src_index + 1] <= xstarts[dest_index]) {
942 src_index++;
943 }
944 while (src_index < row->baseline.segments) {
945 coeffs[dest_index * 3] = row->baseline.quadratics[src_index].a;
946 coeffs[dest_index * 3 + 1] = row->baseline.quadratics[src_index].b;
947 coeffs[dest_index * 3 + 2] = row->baseline.quadratics[src_index].c;
948 dest_index++;
949 src_index++;
950 xstarts[dest_index] = row->baseline.xcoords[src_index];
951 }
952
953 row->baseline = QSPLINE(dest_index, &xstarts[0], &coeffs[0]);
954}