/*--------------------------------------------------------------- spec_pairs "ст", "сл" и др. ----------------------------------------------------------------*/ static void spec_pairs() { struct cut_elm *cut; int16_t i,ip; //текущее и предыдущее сечения SVERS *vers; //текущая версия uchar let,letp; //текущая и предыдущая буквы struct cut_elm *cuts; int16_t is,x0; //правая граница "с" int16_t m_row; //средняя базовая линия det_snap(LC, "special pairs"); i=ncut-1; letp=0; ip=i; while (i>0) { cut=cut_list+i; vers=&cut->versm; let=vers->vers[0].let; if (dust(vers)) { cuts=cut_list+cut->px; //левый край dust'а if (cuts->dh != 0 && //dust отрезан слева addij(LC,r,cut_list,vers_list,ncut,cuts->px,i,0)==0 && cut->versm.vers[0].prob > cuts->versm.vers[0].prob ) ; //приклеили else if (cut->dh != 0) //dust отрезан справа addij(LC,r,cut_list,vers_list,ncut,i,ip,0); } else if ( cut->dh != 0 && strchr("кКтТуУ",let) && !is_russian_baltic_conflict(let) && // 17.07.2001 E.P. !is_russian_turkish_conflict(let)&& // 21.05.2002 E.P. (letp==(uchar)'г' || letp==(uchar)'Г') ) { int16_t j,il=cut->px; int16_t x0=cut->x-((cut_list[ip].x-cut->x)>>1); uchar *letr=&cut_list[ip].versm.vers[0].let; for (j=i-1,cuts=cut-1; j>il && cuts->x >= x0; j--,cuts--) { if (addij(LC,r,cut_list,vers_list,ncut,il,j,0)>1) break; // if (cut_list[j].versm.vers[0].prob<trs2) // break; if (addij(LC,r,cut_list,vers_list,ncut,j,ip,0)>1) continue; if ( (*letr==(uchar)'т' || *letr==(uchar)'Т') && !is_russian_baltic_conflict(*letr) && // 17.07.2001 E.P. !is_russian_turkish_conflict(*letr) // 21.05.2002 E.P. ) break; } } else { if (cut->dh != 0 &&
int16_t erection_incline_word_set(cell *b, cell *e) { cell *c ; int32_t inc ; if( (inc=get_incline_of_word(b,e))==0 ) { for( c=b; c!=e; c=c->next) { c->pos_inc=erect_no; c->stick_inc = NO_INCLINE; c->save_stick_inc = NO_INCLINE; } return 0; } for( c=b; c!=e; c=c->next) { // rotate cell images if( c->stick_inc!=NO_INCLINE && (((long)c->stick_inc*c->h)/204l)>16 && ( (c->flg==c_f_bad) && c->stick_inc<max_incline || c->nvers>0 && (memchr(incline_chars,c->vers[0].let,sizeof(incline_chars)) && !is_russian_baltic_conflict(c->vers[0].let)&&// 17.07.2001 E.P. !is_russian_turkish_conflict(c->vers[0].let) // 21.05.2002 E.P. || erect_solid_stick(c))) ) c->save_stick_inc=c->stick_inc; else c->save_stick_inc=(uchar)inc; c->pos_inc=erect_no; c->stick_inc = NO_INCLINE; } return (int16_t)inc; }
Bool test_incline_of_word(cell *b,cell *e,int32_t inc) { //Bool ret=TRUE; cell * c; int16_t i,wn, up,let; for(up=let=i=0, c=b; c!=e; c=c->next, i++) { if( c->flg&(c_f_let|c_f_bad) ) { let++; if( c->stick_inc!=NO_INCLINE && (((long)c->stick_inc*c->h)/204l)>16 && ( (c->flg==c_f_bad) && c->stick_inc<max_incline || c->nvers>0 && (memchr(incline_chars,c->vers[0].let,sizeof(incline_chars)) && !is_russian_baltic_conflict(c->vers[0].let)&&// 17.07.2001 E.P. !is_russian_turkish_conflict(c->vers[0].let) // 21.05.2002 E.P. || erect_solid_stick(c))) ) wn=erect_cell_width (c, (int16_t)(c->stick_inc)); else wn=erect_cell_width(c, (int16_t)(inc)); if( wn>c->w+1 ) { up++; } } } return !(up*2>let&&let>2); }
void criteries() { cell *c; if (!line_number || current_fragment!=curr_frag) { dist_point_of_i_1=dist_point_of_i_2=dist_point_of_i_3= dist_point_of_i_b=0; curr_frag=current_fragment; } c=cell_f(); while ((c=c->nextl)->nextl != NULL) { criteria(c); if(language == PUMA_LANG_RUSSIAN ) { r_criteria(c,NULL); if( c->nvers>0 && memchr("’вѓЈ",c->vers[0].let,4) && !is_russian_baltic_conflict(c->vers[0].let)&& // 17.07.2001 E.P. !is_russian_turkish_conflict(c->vers[0].let) // 21.05.2002 E.P. ) stick_center_study(c,NULL,1); } } }
/******************************************************** * * * Special programs for Й * * * ********************************************************/ #include <stdlib.h> #include <stdio.h> #include <string.h> #include "func.h" #include "struct.h" #include "linear.h" #include "linutil.h" #include "ligas.h" #include "func.h" #include "minmax.h" extern uchar p2_active; // Discrim й by base lines * static int16_t rec_ii(cell*c,cell*cap); static int16_t rec_ii_halo(cell * c); static uchar iot_pen_lc[]= { 120,60,10,0,0 }; static uchar iot_pen_uc[]= { 140,10,0 ,0,0 }; int16_t cut_by_pos_ii(s_glue * const gl,uchar let) { B_LINES bl; int16_t pen=0,upper=32000,dis,i; get_b_lines(gl->celist[0],&bl); for(i=0; i < gl->ncell; i++) upper = MIN(upper,gl->celist[i]->row); if(let==(uchar)'\xa9' /* й */ && !is_russian_turkish_conflict(let) // 21.05.2002 E.P. ) { if((dis=upper-bl.b2) <= 0) { // letter upper than bbs2 dis = abs(dis); if(dis < 5) pen = iot_pen_lc[dis]; } else pen = 160; // letter lower than bbs2 if( gl->ncell==1 && (gl->celist[0]->recsource == c_rs_ev || gl->celist[0]->recsource == (c_rs_ev|c_rs_deskr) ))// events brought vers if((Ns1+Ns2)>0 && bl.b2-bl.b1>6) { dis=upper-bl.b1; pen += dis<3 ? 60 : 0; } } if(let==(uchar)'\x89' /* Й */) { // Capital iot if((dis=upper-bl.b1) <= 0 ) { // letter upper than bbs1 dis = abs(dis); if(dis < 5) pen = iot_pen_uc[dis]; } else pen = 160; // letter lower than bbs1 } return pen; } // Go by string and recog '\xa9' /* й */ void proc_ii(void) { cell * c,*cap; uchar let; int16_t ndust; c = cell_f(); while((c=c->nextLetter()) != NULL ) { if( !c->hasCellFlag(c_f_let + c_f_bad)) continue; let = c->vers[0].let; ndust=0; //if( !memchr("иИнНпыў",let,7) || if( !memchr("\xA8\x88\xAD\x8D\xAF\xEB\xF7",let,7) || is_russian_baltic_conflict(let) // 17.07.2001 E.P. ) continue; cap = c; while((cap=cap->next)!=NULL && cap != c->nextLetter()) { if(cap->isDust()) { ndust++; switch(rec_ii(c,cap)) { case 1: goto next_let; case -1: return; case 0: break; } } } cap = c; while((cap=cap->prev)!=NULL && cap != c->previousLetter()) { if(cap->isDust()) { ndust++; //if(rec_ii(c,cap))goto next_let; switch( rec_ii(c,cap)) { case 1: goto next_let; case -1: return; case 0: break; } } } if( ndust > 1) rec_ii_halo(c); // many dusts, try all together next_let: ; } // while by letters }
void analysis_words(void) { int16_t left,right,flag=0,flag_qual; cell *WB,*WE,*cl; char snap[380],*buf=snap; left=right=0; WB=clbeg; WE=clend; //AK! add crashguard while( (WB->flg & c_f_dust) || (WB->flg & c_f_fict) || (WB->flg & c_f_punct) ) { if ((WB->next == cell_l() || WB->next == NULL) ) return; WB=WB->next; } //AK! add c/g while( (WE->flg & c_f_dust) || (WB->flg & c_f_fict) || (WB->flg & c_f_punct)) { if ((WE->prev == cell_f() || WE->prev == NULL)) return; WE=WE->prev; } if(WB==WE) return; /* ---------------- LEFT -----------------------------*/ if(WB->vers[0].let==left_quocket) left=100; else if((WB->flg & c_f_bad) || (memchr("¢э™",WB->vers[0].let,6) && !is_russian_baltic_conflict(WB->vers[0].let) && // 17.07.2001 E.P. !is_russian_turkish_conflict(WB->vers[0].let)&& // 21.05.2002 E.P. WB->vers[0].prob < MAX_PROB) || (memchr("Cc",WB->vers[0].let,2) && WB->vers[0].prob < MIN_PROB) || (memchr("u",WB->vers[0].let,1) && WB->vers[0].prob <=SMAX_PROB && WB->h <= ok_K_hgt) || (WB->vers[0].let== r_cu_u && WB->vers[0].prob < MID_PROB) || (memchr("ae",WB->vers[0].let,2) && WB->vers[0].prob < MAX_PROB) ) { if(WB->vers[0].prob<MIN_PROB && (WB->h>>1)*3 <= (WB->nextl)->h) flag_qual=1; else flag_qual=0; if(WB->vers[0].let=='1') flag_qual=0; left=check_shevron(WB,flag_qual); }
int16_t get_baton_inc(cell *c) { int16_t n, inc=0; STICK *res,*r; uchar let; if( c->nvers<1 ) return 0; let = decode_ASCII_to_[c->vers[0].let][0]; n=sticks_in_letter(c,0,&res); r=res; if (n>=0) { switch( let ) { case (uchar)'ѕ': case (uchar)'п': if (is_russian_baltic_conflict(let)) // 17.07.2001 E.P. {inc=1;break;} if( n==2 && abs(r[1].incl-r[0].incl)<50 ) inc=r[1].incl; break; case (uchar)'„': case (uchar)'ч': if( n==2 && abs(r[1].incl-r[0].incl)<50 ) inc=r[1].incl; else if( n==1 ) inc=r[0].incl; break; case (uchar)'“': case (uchar)'т': if( n==1 ) inc=r[0].incl; break; default: inc=1; break; } } else return 0; return inc; }
/*--------------------------------------------------------------------- r2l процесс последовательного отрезания букв справа на интервале (ib2,ie2) (или (ib1,ie2), если справа буква из списка); заканчивается, если весь интервал хорошо разрезался или очередная граница совпала с вершиной оптимального пути слева; вычисляет новые значения ie1, ie2, ir; ---------------------------------------------------------------------*/ static char r2l(int16_t *ir, int16_t *ie2, int16_t *ie1, int16_t mode) { int16_t i,x0; uchar let; seg_vers *cur_vers; struct cut_elm *cut; char cc; int16_t ie2p; //предыдущая ie2 struct cut_elm *cutb; //граница при движении по связным компонентам int16_t pmax; //наилучший результат int16_t set; //индекс множества точек разрезания int16_t ie0; int16_t wmin,wmax; //допустимая ширина буквы: мин. и макс. ie2p=*ie1; *ir=ibc=*ie2; cutb=cut_list+ibc; while (ibc > 0) { if (connect_) { //выбираем компоненту, добавляя узкие куски, лежащие недалеко x0=cut_list[*ie2].x; for (i=ibc-1,cut=cutb-1; i>=0; i--,cut--) { if (cut->dh != 0) continue; if (cut->rv.v3 > minp) break; //широкий просвет if (cutb->x-cut->x > sym_width && x0-cutb->x > sym_width) break; ibc=i; cutb=cut; //кандидат на конец } if (i<0) { i++; cut++; } if (cutb->x-cut->x <= sym_width || x0-cutb->x <= sym_width) { ibc=i; cutb=cut; } } else ibc=0; //режем *ir=*ie2; while (*ir > ibc) { version *vers0; char *ilet; int16_t ie1p=*ie1; if (ib2<*ie2 && ibc<=ib2 && cut_list[*ie2].x-cut_list[ib2].x <= w2) { ie0=*ie2; if ((addij(LC,r,cut_list,vers_list,ncut,ib2,ie0,0) & (2+4+8)) == 0) if (cut_list[*ie2].versm.vers[0].prob>trs2) { *ie1=*ir=ib2; goto accept; } } pmax=-1; wmin=w1; wmax=w2; for (set=1; set<=3; set++) { ie0=*ie2; //пробуем следующую cc=rcut_out(ibc,ie0,ie0,wmin,wmax,set,trs2,ir,&pmax,mode); if (cc) { *ie1=*ir; goto accept; } } wmin=minw; wmax=h2; for (set=1; set<=4; set++) { ie0=*ie2; cc=rcut_out(ibc,ie0,ie0,wmin,wmax,set,trs2,ir,&pmax,mode); //пробуем следующую if (cc) { *ie1=*ir; goto accept; } if (*ie1 != *ie2) { //справа буква может быть частью более широкой ie0=*ie1; cc=rcut_out(ibc,*ie2,ie0,minw,h2,set,trs2,ir,&pmax,mode); //расширяем предыдущую if (cc) { *ie1=*ie2; goto accept; } } } if (*ie2<ie2p) { ie0=*ie2; cc=radjust_cut(ibc,ir,&ie0,ie2p,minw,&pmax,mode); if (cc) { *ie1=*ir; goto accept; } } return 0; accept: *ie2=*ir; ie2p=ie0; let=0; if (cur_vers=find_vers(*ir,ie0,vers_list)) { vers0=&cur_vers->vers.vers[0]; let=vers0->let; if (let=='-') *ie1=ie1p; else if ( (let==(uchar)'т' || strchr(sticks_right_to_bad,let) ) && !is_russian_baltic_conflict(let) && // 17.07.2001 E.P. !is_russian_turkish_conflict(let) // 21.05.2002 E.P. ) *ie1=ie0; else if ( (ilet=strchr(letters_right_to_bad,let))!=0 && !is_russian_baltic_conflict(let) // 17.07.2001 E.P. ) if (vers0->prob < prob_right_to_bad[(uchar*)ilet-letters_right_to_bad]) *ie1=ie0; //может быть частью буквы } if (debug_on) #ifndef MY_DEBUG if (det_trace) #endif { sprintf(snap_text,"keep: (%d,%d) %c",*ir,ie0,let); show_and_wait(snap_text); } if (ib2>=*ie2) if (ib2==*ie2 || on_path(*ie2,ib2,cut_list)) return 1; } } return 1; }
/*--------------------------------------------------------------------- l2r процесс последовательного отрезания букв слева на интервале (*b2,ie2) (или (*b1,ie2), если слева буква из списка); заканчивается, если весь интервал хорошо разрезался или очередная граница совпала с вершиной оптимального пути справа; вычисляет новые значения ib1, ib2, il; ---------------------------------------------------------------------*/ static char l2r(int16_t *ib1, int16_t *ib2, int16_t *il) { int16_t i,x0; uchar let; struct cut_elm *cut; char cc; int16_t ib2p; //предыдущая ib2 struct cut_elm *cute;//граница при движении по связным компонентам int16_t pmax; //наилучший результат int16_t set; //индекс множества точек разрезания int16_t ib0; int16_t wmin,wmax; //допустимая ширина буквы: мин. и макс. ib2p=*ib1; *il=iec=*ib2; cute=cut_list+iec; while (iec < iemax) { if (connect_) { //выбираем компоненту, добавляя узкие куски, лежащие недалеко x0=cut_list[*ib2].x; for (i=iec+1,cut=cute+1; i<=iemax; i++,cut++) { if (cut->dh != 0) continue; if (cut->rv.v3 > minp) break; //широкий просвет if (cut->x-cute->x > sym_width && cute->x-x0 > sym_width) break; iec=i; cute=cut; //кандидат на конец } if (i>iemax) { i--; cut--; } if (cut->x-cute->x <= sym_width || cute->x-x0 <= sym_width) { iec=i; cute=cut; } } else iec=iemax; //режем *il=*ib2; while (*il<iec) { version *vers0; char *ilet; int16_t ib1p=*ib1; if (*ib2<ie2 && ie2<=iec && cut_list[ie2].x-cut_list[*ib2].x <= w2) { ib0=*ib2; if ((addij(LC,r,cut_list,vers_list,ncut,ib0,ie2,0) & (2+4+8)) == 0) if (cut_list[ie2].versm.vers[0].prob>trs2) { *ib1=*il=ie2; goto accept; } } pmax=-1; wmin=w1; wmax=w2; for (set=1; set<=3; set++) { ib0=*ib2; //пробуем следующую cc=lcut_out(ib0,*ib2,iec,wmin,wmax,set,trs2,il,&pmax); if (cc) { *ib1=*il; goto accept; } } wmin=minw; wmax=h2; for (set=1; set<=4; set++) { ib0=*ib2; cc=lcut_out(ib0,*ib2,iec,wmin,wmax,set,trs2,il,&pmax); //пробуем следующую if (cc) { *ib1=*il; goto accept; } if (*ib1 != *ib2) { //слева буква может быть частью более широкой ib0=*ib1; cc=lcut_out(ib0,*ib2,iec,minw,h2,set,trs2,il,&pmax); //расширяем предыдущую if (cc) { *ib1=*ib2; goto accept; } } } if (*ib2>ib2p) { ib0=*ib2; cc=ladjust_cut(ib2p,&ib0,il,iec,minw,&pmax); if (cc) { *ib1=*il; goto accept; } } return 0; accept: *ib2=*il; ib2p=ib0; let=0; vers0=&cut_list[*il].versm.vers[0]; let=vers0->let; if (let=='-') *ib1=ib1p; else if ( (let==(uchar)'т' || let==(uchar)'ш' || let==(uchar)'Ш' || strchr(sticks_left_to_bad,let) ) && !is_russian_baltic_conflict(let) &&// 17.07.2001 E.P. !is_russian_turkish_conflict(let) // 21.05.2002 E.P. ) *ib1=ib0; else if ( (ilet=strchr(letters_left_to_bad,let))!=0 && !is_russian_baltic_conflict(let) // 17.07.2001 E.P. ) if (vers0->prob < prob_left_to_bad[(uchar*)ilet-letters_left_to_bad]) *ib1=ib0; //может быть частью буквы if (debug_on) #ifndef MY_DEBUG if (det_trace) #endif { sprintf(snap_text,"keep: (%d,%d) %c",ib0,*il,let); show_and_wait(snap_text); } if (*ib2>=ie2) if (*ib2==ie2 || on_path(*ib2,iemax,cut_list)) return 1; if ( (let==(uchar)'ь' || let==(uchar)'Ь') && !is_russian_baltic_conflict(let) // 17.07.2001 E.P. ) { fl_b=1; return 0; } } } return 1; }
/*------------------------------------------------------------------ dp_pass0 линейный проход в растре r на множестве ncut точек cut_list; vers_list - результаты для отдельных сегментов; LC - cell слева от растра ------------------------------------------------------------------*/ void dp_pass0(cell *CP, raster *rp, struct cut_elm *cutp, seg_vers **versp, int16_t n) { int16_t i,j,x; int16_t i1,i2; uchar let; int16_t cc; struct cut_elm *cut; SVERS *vers; int16_t pass; // seg_vers *cur_vers; if ((ncut=n)<2) return; LC=CP; r=rp; cut_list=cutp; vers_list=versp; iemax=ncut-1; right_dust=0; fl_b=0; connect_=1; ie1=iemax; vers=&cut_list[ie1].versm; ie2=ir=(let(vers) || dust(vers)) ? ie1-1 : ie1; ib1=ib2=0; vers=&cut_list[1].versm; if (let(vers)) ib2=1; else if (cut_list->gvarm & c_cg_cutdone) ib2=on_path(0,ie2,cut_list); iec=ib2; ibc=ie2; w1=sym_width-(sym_width>>2); w2=sym_width+(sym_width>>2); h2=r->h<<1; cut=cut_list+ie1; /* //отщепляем правые dust'ы if (dust(&cut->versm) && cut->duflm==0) { right_dust=1; iemax--; cut--; // if (dust(&cut->versm) && cut->duflm==0) iemax--; ir=ie1=ie2=iemax; } */ //крайние хорошие распознаем с сопутствующими dust'ами if (ie1 != ie2 && cut->duflm) addij(LC,r,cut_list,vers_list,ncut,ie2,ie1,0); if (ib1 != ib2) { cut=cut_list+ib2; if (cut->duflm) addij(LC,r,cut_list,vers_list,ncut,ib1,ib2,0); if ((let=cut->versm.vers[0].let)==(uchar)'ь' && !is_russian_baltic_conflict(let) || // 17.07.2001 E.P. let==(uchar)'Ь' ) fl_b=1; } if (ib2>=ie2) { addij(LC,r,cut_list,vers_list,ncut,ib1,ie1,0); goto test_right_dust; } do { if (!fl_b && iec != iemax) { #ifndef MY_DEBUG if (det_trace) #endif cg_show_rast(LC,r,"left to right",cut_list); //растр - на экран cc=l2r(&ib1,&ib2,&il); if (cc) goto finish; if (il<iemax && iec>il && (cut=cut_list+il)->dh==0 && (x=cut->x-cut_list->x) < h2 && x > sym_width>>1 && cut->versm.vers[0].prob>=190 && !not_connect_sect(0,il,cut_list)) { //оставим, как есть, и попробуем дальше i1=i2=il; cc=l2r(&i1,&i2,&i); if (cc) //дальше - хорошо, вернемся к подозрительному участку { if (debug_on) #ifndef MY_DEBUG if (det_trace) #endif { sprintf(snap_text,"right side reached, return %d-%d",0,il); cg_show_rast(LC,r,snap_text,cut_list); //растр - на экран } ib1=i1; ib2=i2; i1=i2=il; il=i; cc=r2l(&i,&i2,&i1,0); goto finish; } } } if (ibc != 0 && abs(cut_list[ie2].x-cut_list[ib2].x)>minw) { //слева не вышло, пробуем справа налево if (debug_on) #ifndef MY_DEBUG if (det_trace) #endif { sprintf(snap_text,"left: reliable=%d advance=%d; try right",ib2,il); cg_show_rast(LC,r,snap_text,cut_list); //растр - на экран } cc=r2l(&ir,&ie2,&ie1,2); if (cc) goto finish; if (ir>0 && ibc<ir && (cut=cut_list+ir)->dh==0 && (x=cut_list[iemax].x-cut->x) < h2 && x > sym_width>>1 && cut_list[iemax].versm.vers[0].prob>=190 && !not_connect_sect(ir,iemax,cut_list)) { //оставим, как есть, и попробуем дальше i1=i2=ie2; cc=r2l(&i,&i2,&i1,2); if (cc) //дальше - хорошо, вернемся к подозрительному участку { if (debug_on) #ifndef MY_DEBUG if (det_trace) #endif { sprintf(snap_text,"left side reached, return %d-%d",ir,iemax); cg_show_rast(LC,r,snap_text,cut_list); //растр - на экран } ie1=i1; ie2=i2; i1=i2=ir; ir=i; cc=l2r(&i1,&i2,&i); goto finish; } } } if (abs(cut_list[ie2].x-cut_list[ib2].x)<=minw) { j=on_path(ie2,iemax,cut_list); if (j==0) break; if (ib2==0) addij(LC,r,cut_list,vers_list,ncut,0,j,0); else one_cut(cut_list[ib2].px,ib2,ie2,j); goto test_right_dust; } if (il==ie2 && (iec>il || iec==iemax) && ir==ib2 && (ibc<ir || ibc==0) && cut_list[ie2].versm.vers[0].prob>MINlet) goto finish; if (il==ie2 && (iec>il || iec==iemax) || ir==ib2 && (ibc<ir || ibc==0)) if (cut_list[ie2].versm.vers[0].prob>=190) goto finish; if (il==ir) { version *vers0; char *ilet; if (connect_ && cut_list[il].dh==0) { addij(LC,r,cut_list,vers_list,ncut,ib2,ie2,0); if (cut_list[ie2].versm.vers[0].prob>trs2) goto finish; } if (ir != ie2 && cut_list[ie2].x-cut_list[ir].x > w2) { i1=i2=ir; if ( l2r(&i1,&i2,&i) || i>0 && on_path(i,iemax,cut_list) && cut_list[i].versm.vers[0].prob>=190) { j=on_path(ir,iemax,cut_list); vers0=&cut_list[j].versm.vers[0]; if ( (let=vers0->let)==(uchar)'т' && !is_russian_baltic_conflict(let) && // 17.07.2001 E.P. !is_russian_turkish_conflict(let) // 21.05.2002 E.P. ) ie1=j; else if ( (ilet=strchr(letters_right_to_bad,let))!=0 && !is_russian_baltic_conflict(let) // 17.07.2001 E.P. ) if (vers0->prob < prob_right_to_bad[(uchar*)ilet-letters_right_to_bad]) ie1=j; //может быть частью буквы ie2=ir; } } if (il != ib2 && cut_list[il].x-cut_list[ib2].x > w2) { i2=il; i1 = (ie2==il) ? ie1 : i2; if (r2l(&i,&i2,&i1,0) || on_path(i,ib2,cut_list) && cut_list[i2].versm.vers[0].prob>=190) { cut=cut_list+il; vers0=&cut->versm.vers[0]; if ((let=vers0->let)==(uchar)'т' && !is_russian_baltic_conflict(let) && // 17.07.2001 E.P. !is_russian_turkish_conflict(let) // 21.05.2002 E.P. ) ib1=cut->px; else if ( (ilet=strchr(letters_right_to_bad,let)) !=0 && !is_russian_baltic_conflict(let) // 17.07.2001 E.P. ) if (vers0->prob < prob_right_to_bad[(uchar*)ilet-letters_right_to_bad]) ie1=cut->px; //может быть частью буквы ib2=il; } } if (ib2==ie2) goto finish; } // if (il>ir) break; // if (iec==iemax || ibc==0 || iec<ibc) break; if (iec==iemax && ibc==0) break; connect_ = 1-connect_; } while (!connect_); if (right_dust) if (glue_right_dust()) { spec_pairs(); return; } if (debug_on) #ifndef MY_DEBUG if (det_trace) #endif { sprintf(snap_text,"right: reliable=%d advance=%d; ",ie2,ir); cg_show_rast(LC,r,snap_text,cut_list); //растр - на экран } //не сошлись, запускаем ДП между ними if (ie1-ib1 <= 2) if (!good_path(cut_list,ncut)) { ib1=ib2=0; ie2=ie1=ncut-1; } DP: if (ie1-ib1 <= 2) { spec_pairs(); return; } il=ib1; ir=ie1; for (pass=1; pass<=4; pass++) { dp_bound(cut_list,vers_list,pass,&il,&ir); if (ir<=il) { if (ib1 != 0 || ie1 != ncut-1) spec_pairs(); //неполное ДП return; } #ifndef MY_DEBUG if (det_trace) #endif { sprintf(snap_text,"try DP %d-%d pass=%d",il,ir,pass); cg_show_rast(LC,r,snap_text,cut_list); //растр - на экран } for ( i=il+1; i<=ir; i++ ) { if ( !ben_cut(cut_list+i) ) //разрешен на данном проходе { snap_newpoint(i); for (j=i-1; j>=il; j--) if ( !ben_cut(cut_list+j) ) if (addij(LC,r,cut_list,vers_list,ncut,j,i,0) & 8) break ; } //8-широк ий } } //pass if (ib1==0 && ie1==ncut-1) return; //полное ДП - больше нечего делать if (good_path(cut_list,ncut)) { spec_pairs(); return; } //ДП по всему участку il=0; ir=ncut-1; for (pass=1; pass<=4; pass++) { dp_bound(cut_list,vers_list,pass,&il,&ir); if (ir<=il) return; if (il>=ib1 && ir<=ie1) return; //на этом интервале уже считали /* { struct cut_elm *cute=cut_list+ir; for (cut=cut_list+(il+1); cut<cute; cut++) if ((cut->var & 0x7F)==40) break; if (cut==cute) return; //новых точек не будет } */ #ifndef MY_DEBUG if (det_trace) #endif { sprintf(snap_text,"try DP %d-%d pass=%d",il,ir,pass); cg_show_rast(LC,r,snap_text,cut_list); //растр - на экран } for ( i=il+1; i<=ir; i++ ) { if ( !ben_cut(cut_list+i) ) //разрешен на данном проходе { snap_newpoint(i); for (j=i-1; j>=il; j--) if ( !ben_cut(cut_list+j) ) if (addij(LC,r,cut_list,vers_list,ncut,j,i,0) & 8) break ; } //8-широк ий } } //pass return; test_right_dust: if (right_dust) glue_right_dust(); if (!good_path(cut_list,ncut)) { ib1=ib2=0; ie2=ie1=ncut-1; goto DP; } spec_pairs(); return; finish: if (right_dust) glue_right_dust(); spec_pairs(); return; }
// erecting all letters with sticks and bad symbols Bool setup_incline_word(cell *b, cell *e, Bool calc) { cell *c , *cs; int16_t inc, ninc, nall; if( calc ) { memset(hist,0,sizeof(hist)); memset(extr,0,sizeof(extr)); } for( nall=ninc=0, c=b; c!=e; c = c->next,nall++) { if( !(c->pos_inc&erect_rot) ) { c->pos_inc=erect_no; c->right=0; if( (c->flg&c_f_let) && // for inclinables images (memchr(incline_chars,c->vers[0].let,sizeof(incline_chars) ) && !is_russian_baltic_conflict(c->vers[0].let)&&// 17.07.2001 E.P. !is_russian_turkish_conflict(c->vers[0].let) // 21.05.2002 E.P. || erect_solid_stick(c)) || (c->flg&c_f_bad) ) // or bad symbols { if( erector(c, 1, 0, 1, 0)==2 ) // set incline in c->stick_inc { } inc=0; if( c->stick_inc!=NO_INCLINE ) inc = c->stick_inc; if( inc>=0 ) { if( calc ) { hist[ inc/16 ]++; } ninc++; cs = c; } } } } if( calc ) { num_extr = 0; if( hist[0]+1==ninc && hist[16]==1 ) return FALSE; if( !(hist[0]*3>ninc*2) && ninc>9) //10 ) { // binarize if few nonIncline images & many incline images for(inc=0;inc<128;inc++) if( hist[ inc ]>=ninc/4 && num_extr<sizeof( extr ) ) extr[ num_extr++ ] = (uchar)inc; } if( num_extr ) max_incline = MAX((extr[ num_extr-1 ]+1)*16,512); else max_incline = 512; if( !num_extr ) { for( c=b; c!=e; c = c->next) { if( c->stick_inc<300 || c->stick_inc<400 && get_baton_inc(c)==0 ) { if( calc ) hist[ c->stick_inc/16 ]--; ninc--; if( !local_pass ) c->stick_inc=0; } } } if( num_extr ) { for( c=b; c!=e; c = c->next) if( !(c->pos_inc&erect_rot) ) { if( (c->flg&c_f_let) && // for inclinables images memchr(aux_inc_chars,c->vers[0].let,sizeof(aux_inc_chars)) && !is_russian_baltic_conflict(c->vers[0].let)&&// 17.07.2001 E.P. !is_russian_turkish_conflict(c->vers[0].let) // 21.05.2002 E.P. ) { inc = 0; erector(c, 1, 0, 1, 1); // set incline in c->stick_inc if( c->stick_inc!=NO_INCLINE ) { inc = c->stick_inc; ninc++; } if( !mode_incline(inc) && inc<300 ) { // non characteristical incline c->pos_inc=erect_no; c->right=0; } } } } line_incline = ( ninc*2>nall ); } else // calc==0 : study one word if( ninc==0 ) return FALSE; return TRUE; }
// // rotate word cells // int16_t erection_incline_word(cell *b, cell *e, int16_t base_3, int16_t n_call) { cell *c, *tmp, *cnext ; int32_t inc, i ; int16_t shave=(erection_enable==2) ; version save_versions[VERS_IN_CELL] ; int16_t save_nvers ; if( (inc=get_incline_of_word(b,e))==0 ) return 0; if( 1&&!test_incline_of_word(b,e,inc) ) return 0; for(i=0, c=b; c!=e; c=c->next, i++) { tmp = c->prev; // left cell cnext=c->next; // right cell if( local_pass ) { if( c->pos_inc&erect_rot ) continue; if( c->stick_inc!=NO_INCLINE && (((long)c->stick_inc*c->h)/204l)>16 && ( (c->flg==c_f_bad) && c->stick_inc<max_incline || c->nvers>0 && (memchr(incline_chars,c->vers[0].let,sizeof(incline_chars)) && !is_russian_baltic_conflict(c->vers[0].let)&&// 17.07.2001 E.P. !is_russian_turkish_conflict(c->vers[0].let) // 21.05.2002 E.P. || erect_solid_stick(c))) ) c->save_stick_inc = c->stick_inc; else c->save_stick_inc = (int16_t)inc; c->pos_inc = erect_rest; continue; } // rotate cell images if( c->stick_inc!=NO_INCLINE && (((long)c->stick_inc*c->h)/204l)>16 && ( (c->flg==c_f_bad) && c->stick_inc<max_incline || c->nvers>0 && (memchr(incline_chars,c->vers[0].let,sizeof(incline_chars)) && !is_russian_baltic_conflict(c->vers[0].let)&&// 17.07.2001 E.P. !is_russian_turkish_conflict(c->vers[0].let) // 21.05.2002 E.P. || erect_solid_stick(c))) ) c=erect_cell_value (c, c->stick_inc, shave , TRUE); else c=erect_cell_value (c, (int16_t)inc, shave , TRUE); for(tmp = tmp->next;tmp!=cnext;tmp=tmp->next) { // shift cell boxes erect_rotate_bl(tmp,base_3,inc,-1);//(int16_t)(line_scale?(base_3>>line_scale):base_3),inc,-1); v2_pidx_crit(tmp); if( (save_nvers = c->nvers)>0 ) memcpy(save_versions,c->vers,VERS_IN_CELL*sizeof(version)); // recognizing corrected images if( (tmp->flg&(c_f_bad|c_f_let)) && !local_pass) { if(n_call==0 ) { if( tmp->nvers>0 && memchr(disable_rerecog,tmp->vers[0].let,sizeof(disable_rerecog) ) && !is_russian_baltic_conflict(tmp->vers[0].let)&&// 17.07.2001 E.P. !is_russian_turkish_conflict(tmp->vers[0].let) // 21.05.2002 E.P. || tmp->nvers<1 ) { short_recog_cell( tmp ); levcut(tmp,1); add_versions(tmp, save_versions, save_nvers); } // end of spec letters for 1 pass } else { s_glue GL={0}; GL.celist[0] = tmp; GL.maxlist[0] = tmp; GL.complist[0] = tmp->env; GL.maxlist[1] = GL.celist[1]=NULL; GL.complist[1] = NULL; GL.ncell = 1; GL.row = tmp->row; GL.col = tmp->col; GL.width = tmp->w; GL.height = tmp->h; if(crecell(tmp,&GL,3)>=0) dmBOX(tmp,&GL); } // end of spec letters for 2 pass } // end of if letter } // end of cykl tmp } return (int16_t)inc; }
// calculate average incline in word int16_t get_incline_of_word(cell *b, cell *e) { cell *c ; int32_t inc, inc1, n1 ; int16_t i, n, mn, all, zeromn ; int16_t inc_list[MAX_LEN_WORD] ; int16_t norm_list[MAX_LEN_WORD] ; int16_t zero, in, zerall ; #define MAX_INCLINE 55 memset(inc_list,0,sizeof(inc_list)); for(n1=inc1=inc=0,zerall=zero=zeromn=all=mn=i=n=0,c=b; c!=e; c=c->next) { if( (c->flg&(c_f_let|c_f_bad)) && c->stick_inc!=NO_INCLINE && c->stick_inc>1 && (memchr(incline_main, c->vers[0].let, sizeof(incline_main)) && !is_russian_baltic_conflict(c->vers[0].let) &&// 17.07.2001 E.P. !is_russian_turkish_conflict(c->vers[0].let)// 21.05.2002 E.P. || c->stick_inc<max_incline) && c->nvers>0 && ( (memchr(incline_chars,c->vers[0].let,sizeof(incline_chars) ) && !is_russian_baltic_conflict(c->vers[0].let)&&// 17.07.2001 E.P. !is_russian_turkish_conflict(c->vers[0].let) // 21.05.2002 E.P. || erect_solid_stick(c) ) || memchr(aux_inc_chars,c->vers[0].let,sizeof(aux_inc_chars) ) && !is_russian_baltic_conflict(c->vers[0].let)&&// 17.07.2001 E.P. !is_russian_turkish_conflict(c->vers[0].let) // 21.05.2002 E.P. ) ) { inc += c->stick_inc; norm_list[n] = c->stick_inc; n++; if( c->nvers>0 && memchr(incline_main,c->vers[0].let,sizeof(incline_main)) && !is_russian_baltic_conflict(c->vers[0].let) && // 17.07.2001 E.P. !is_russian_turkish_conflict(c->vers[0].let)&&// 21.05.2002 E.P. no_bad_alias(c) ) mn++; if( (c->flg&c_f_bad)&&mode_incline(c->stick_inc) ) mn++; } else if( (c->flg&c_f_bad) && mode_incline(c->stick_inc) ) inc_list[i++] = c->stick_inc; if( c->stick_inc==0 ) zerall++; if( (c->flg&c_f_let) && c->stick_inc==0 ) { if( c->nvers && memchr(incline_main,c->vers[0].let,sizeof(incline_main)) && !is_russian_baltic_conflict(c->vers[0].let)&& // 17.07.2001 E.P. !is_russian_turkish_conflict(c->vers[0].let) // 21.05.2002 E.P. ) zeromn++; else if( c->nvers && '|'==c->vers[0].let && c->h>16 ) zeromn++; } if( (c->flg&c_f_let) && c->stick_inc==0 && c->nvers>0 && (memchr(incline_chars,c->vers[0].let,sizeof(incline_chars) ) && !is_russian_baltic_conflict(c->vers[0].let)&&// 17.07.2001 E.P. !is_russian_turkish_conflict(c->vers[0].let) // 21.05.2002 E.P. || erect_solid_stick(c)) ) zero++; if((c->flg&c_f_let) && c->stick_inc!=NO_INCLINE && c->stick_inc>1 && c->nvers>0 && (memchr(incline_chars,c->vers[0].let,sizeof(incline_chars) ) && !is_russian_baltic_conflict(c->vers[0].let)&&// 17.07.2001 E.P. !is_russian_turkish_conflict(c->vers[0].let) // 21.05.2002 E.P. || erect_solid_stick(c)) ) { inc1 += c->stick_inc; n1++; } if( (c->flg&c_f_let) ) all++; } if( n==0 ) { if( i ) return ( represent_inc(inc_list,i, 64) ); else if(n1>0 && n1*2>all && line_incline ) { inc1 /= n1; if( inc1<300 ) inc1=0; return (uchar)inc1; } else return 0; } else { if( (in=represent_inc(norm_list,n, 64))!=0 && num_inc_in_list(norm_list,n)>2 ) inc = in; else inc /= n; } // delete incline for small statistic if( inc<100 ) inc = 0; // too small incline if( mn==0 && ( num_extr==0 && n*5<all*3 || all==1 )) inc = 0; // too few inclineable images if( mn==1 && num_extr==0 && nIncline>=MAX_INCLINE && inc-nIncline<=256 ) inc = 0; // too few inclineable images & large line incline if( inc<300 && // small incline (zeromn>1 || hist[0]>5) && // exist zero inc in word or line (num_extr==0||num_extr==2 && extr[0]==0&&extr[1]<=16) && // non inc line (nIncline>=MAX_INCLINE && inc-nIncline<=256 || // large line incline zero>2 && mn<2) ) // many zero inc in word & 1 inc inc = 0; if( inc<350 && mn==0 && all<4 && zeromn>0 ) inc=0; if( mn==1 && zeromn>1 ) // many zero inc in word & 1 inc inc = 0; if( mn==1 && zeromn>=1 && nIncline>=MAX_INCLINE ) inc = 0; if( zeromn && zerall>MAX(all/3,2) && num_extr==0 && inc>max_incline ) inc = 0; if( inc>700 && mn<2 && !num_extr ) // big incline & too few inclineables letsx inc = 0; // set new inc during bad letter with good incline if( inc==0 && all<2 && num_extr ) { int16_t num, ii; inc1 = represent_inc(inc_list,i, 64); for(num=ii=0;ii<i;ii++) if(inc_list[ii]==inc1) num++; if( num==i ) inc = inc1; } return (int16_t)inc; }