int QDockAreaLayout::layoutItems( const QRect &rect, bool testonly ) { if ( !dockWindows || !dockWindows->first() ) return 0; dirty = FALSE; // some corrections QRect r = rect; if ( orientation() == Vertical ) r.setHeight( r.height() - 3 ); // init lines.clear(); ls.clear(); QPtrListIterator<QDockWindow> it( *dockWindows ); QDockWindow *dw = 0; int start = start_pos( r, orientation() ); int pos = start; int sectionpos = 0; int linestrut = 0; QValueList<DockData> lastLine; int tbstrut = -1; int maxsize = size_extent( rect.size(), orientation() ); int visibleWindows = 0; // go through all widgets in the dock while ( ( dw = it.current() ) != 0 ) { ++it; if ( dw->isHidden() ) continue; ++visibleWindows; // find position for the widget: This is the maximum of the // end of the previous widget and the offset of the widget. If // the position + the width of the widget dosn't fit into the // dock, try moving it a bit back, if possible. int op = pos; int dockExtend = dock_extent( dw, orientation(), maxsize ); if ( !dw->isStretchable() ) { pos = QMAX( pos, dw->offset() ); if ( pos + dockExtend > size_extent( r.size(), orientation() ) - 1 ) pos = QMAX( op, size_extent( r.size(), orientation() ) - 1 - dockExtend ); } if ( !lastLine.isEmpty() && !dw->newLine() && space_left( rect, pos, orientation() ) < dockExtend ) shrink_extend( dw, dockExtend, space_left( rect, pos, orientation() ), orientation() ); // if the current widget doesn't fit into the line anymore and it is not the first widget of the line if ( !lastLine.isEmpty() && ( space_left( rect, pos, orientation() ) < dockExtend || dw->newLine() ) ) { if ( !testonly ) // place the last line, if not in test mode place_line( lastLine, orientation(), linestrut, size_extent( r.size(), orientation() ), tbstrut, maxsize, this ); // remember the line coordinats of the last line if ( orientation() == Horizontal ) lines.append( QRect( 0, sectionpos, r.width(), linestrut ) ); else lines.append( QRect( sectionpos, 0, linestrut, r.height() ) ); // do some clearing for the next line lastLine.clear(); sectionpos += linestrut; linestrut = 0; pos = start; tbstrut = -1; } // remeber first widget of a line if ( lastLine.isEmpty() ) { ls.append( dw ); // try to make the best position int op = pos; if ( !dw->isStretchable() ) pos = QMAX( pos, dw->offset() ); if ( pos + dockExtend > size_extent( r.size(), orientation() ) - 1 ) pos = QMAX( op, size_extent( r.size(), orientation() ) - 1 - dockExtend ); } // do some calculations and add the remember the rect which the docking widget requires for the placing QRect dwRect(pos, sectionpos, dockExtend, dock_strut( dw, orientation() ) ); lastLine.append( DockData( dw, dwRect ) ); if ( ::qt_cast<QToolBar*>(dw) ) tbstrut = QMAX( tbstrut, dock_strut( dw, orientation() ) ); linestrut = QMAX( dock_strut( dw, orientation() ), linestrut ); add_size( dockExtend, pos, orientation() ); } // if some stuff was not placed/stored yet, do it now if ( !testonly ) place_line( lastLine, orientation(), linestrut, size_extent( r.size(), orientation() ), tbstrut, maxsize, this ); if ( orientation() == Horizontal ) lines.append( QRect( 0, sectionpos, r.width(), linestrut ) ); else lines.append( QRect( sectionpos, 0, linestrut, r.height() ) ); if ( *(--lines.end()) == *(--(--lines.end())) ) lines.remove( lines.at( lines.count() - 1 ) ); it.toFirst(); bool hadResizable = FALSE; while ( ( dw = it.current() ) != 0 ) { ++it; if ( !dw->isVisibleTo( parentWidget ) ) continue; hadResizable = hadResizable || dw->isResizeEnabled(); dw->updateSplitterVisibility( visibleWindows > 1 ); //!dw->area()->isLastDockWindow( dw ) ); } return sectionpos + linestrut; }
// Extracts Tesseract features and appends them to the features vector. // Startpt to lastpt, inclusive, MUST have the same src_outline member, // which may be NULL. The vector from lastpt to its next is included in // the feature extraction. Hidden edges should be excluded by the caller. // If force_poly is true, the features will be extracted from the polygonal // approximation even if more accurate data is available. static void ExtractFeaturesFromRun( const EDGEPT* startpt, const EDGEPT* lastpt, const DENORM& denorm, double feature_length, bool force_poly, GenericVector<INT_FEATURE_STRUCT>* features) { const EDGEPT* endpt = lastpt->next; const C_OUTLINE* outline = startpt->src_outline; if (outline != NULL && !force_poly) { // Detailed information is available. We have to normalize only from // the root_denorm to denorm. const DENORM* root_denorm = denorm.RootDenorm(); int total_features = 0; // Get the features from the outline. int step_length = outline->pathlength(); int start_index = startpt->start_step; // pos is the integer coordinates of the binary image steps. ICOORD pos = outline->position_at_index(start_index); // We use an end_index that allows us to use a positive increment, but that // may be beyond the bounds of the outline steps/ due to wrap-around, to // so we use % step_length everywhere, except for start_index. int end_index = lastpt->start_step + lastpt->step_count; if (end_index <= start_index) end_index += step_length; LLSQ prev_points; LLSQ prev_dirs; FCOORD prev_normed_pos = outline->sub_pixel_pos_at_index(pos, start_index); denorm.NormTransform(root_denorm, prev_normed_pos, &prev_normed_pos); LLSQ points; LLSQ dirs; FCOORD normed_pos; int index = GatherPoints(outline, feature_length, denorm, root_denorm, start_index, end_index, &pos, &normed_pos, &points, &dirs); while (index <= end_index) { // At each iteration we nominally have 3 accumulated sets of points and // dirs: prev_points/dirs, points/dirs, next_points/dirs and sum them // into sum_points/dirs, but we don't necessarily get any features out, // so if that is the case, we keep accumulating instead of rotating the // accumulators. LLSQ next_points; LLSQ next_dirs; FCOORD next_normed_pos; index = GatherPoints(outline, feature_length, denorm, root_denorm, index, end_index, &pos, &next_normed_pos, &next_points, &next_dirs); LLSQ sum_points(prev_points); // TODO(rays) find out why it is better to use just dirs and next_dirs // in sum_dirs, instead of using prev_dirs as well. LLSQ sum_dirs(dirs); sum_points.add(points); sum_points.add(next_points); sum_dirs.add(next_dirs); bool made_features = false; // If we have some points, we can try making some features. if (sum_points.count() > 0) { // We have gone far enough from the start. Make a feature and restart. FCOORD fit_pt = sum_points.mean_point(); FCOORD fit_vector = MeanDirectionVector(sum_points, sum_dirs, prev_normed_pos, normed_pos); // The segment to which we fit features is the line passing through // fit_pt in direction of fit_vector that starts nearest to // prev_normed_pos and ends nearest to normed_pos. FCOORD start_pos = prev_normed_pos.nearest_pt_on_line(fit_pt, fit_vector); FCOORD end_pos = normed_pos.nearest_pt_on_line(fit_pt, fit_vector); // Possible correction to match the adjacent polygon segment. if (total_features == 0 && startpt != endpt) { FCOORD poly_pos(startpt->pos.x, startpt->pos.y); denorm.LocalNormTransform(poly_pos, &start_pos); } if (index > end_index && startpt != endpt) { FCOORD poly_pos(endpt->pos.x, endpt->pos.y); denorm.LocalNormTransform(poly_pos, &end_pos); } int num_features = ComputeFeatures(start_pos, end_pos, feature_length, features); if (num_features > 0) { // We made some features so shuffle the accumulators. prev_points = points; prev_dirs = dirs; prev_normed_pos = normed_pos; points = next_points; dirs = next_dirs; made_features = true; total_features += num_features; } // The end of the next set becomes the end next time around. normed_pos = next_normed_pos; } if (!made_features) { // We didn't make any features, so keep the prev accumulators and // add the next ones into the current. points.add(next_points); dirs.add(next_dirs); } } } else { // There is no outline, so we are forced to use the polygonal approximation. const EDGEPT* pt = startpt; do { FCOORD start_pos(pt->pos.x, pt->pos.y); FCOORD end_pos(pt->next->pos.x, pt->next->pos.y); denorm.LocalNormTransform(start_pos, &start_pos); denorm.LocalNormTransform(end_pos, &end_pos); ComputeFeatures(start_pos, end_pos, feature_length, features); } while ((pt = pt->next) != endpt); } }
inT32 C_OUTLINE::count_transitions( //winding number inT32 threshold //on size ) { BOOL8 first_was_max_x; //what was first BOOL8 first_was_max_y; BOOL8 looking_for_max_x; //what is next BOOL8 looking_for_min_x; BOOL8 looking_for_max_y; //what is next BOOL8 looking_for_min_y; int stepindex; //current step inT32 total_steps; //steps to do //current limits inT32 max_x, min_x, max_y, min_y; inT32 initial_x, initial_y; //initial limits inT32 total; //total changes ICOORD pos; //position of point ICOORD next_step; //step to next pix pos = start_pos (); total_steps = pathlength (); total = 0; max_x = min_x = pos.x (); max_y = min_y = pos.y (); looking_for_max_x = TRUE; looking_for_min_x = TRUE; looking_for_max_y = TRUE; looking_for_min_y = TRUE; first_was_max_x = FALSE; first_was_max_y = FALSE; initial_x = pos.x (); initial_y = pos.y (); //stop uninit warning for (stepindex = 0; stepindex < total_steps; stepindex++) { //all intersected next_step = step (stepindex); pos += next_step; if (next_step.x () < 0) { if (looking_for_max_x && pos.x () < min_x) min_x = pos.x (); if (looking_for_min_x && max_x - pos.x () > threshold) { if (looking_for_max_x) { initial_x = max_x; first_was_max_x = FALSE; } total++; looking_for_max_x = TRUE; looking_for_min_x = FALSE; min_x = pos.x (); //reset min } } else if (next_step.x () > 0) { if (looking_for_min_x && pos.x () > max_x) max_x = pos.x (); if (looking_for_max_x && pos.x () - min_x > threshold) { if (looking_for_min_x) { initial_x = min_x; //remember first min first_was_max_x = TRUE; } total++; looking_for_max_x = FALSE; looking_for_min_x = TRUE; max_x = pos.x (); } } else if (next_step.y () < 0) { if (looking_for_max_y && pos.y () < min_y) min_y = pos.y (); if (looking_for_min_y && max_y - pos.y () > threshold) { if (looking_for_max_y) { initial_y = max_y; //remember first max first_was_max_y = FALSE; } total++; looking_for_max_y = TRUE; looking_for_min_y = FALSE; min_y = pos.y (); //reset min } } else { if (looking_for_min_y && pos.y () > max_y) max_y = pos.y (); if (looking_for_max_y && pos.y () - min_y > threshold) { if (looking_for_min_y) { initial_y = min_y; //remember first min first_was_max_y = TRUE; } total++; looking_for_max_y = FALSE; looking_for_min_y = TRUE; max_y = pos.y (); } } } if (first_was_max_x && looking_for_min_x) { if (max_x - initial_x > threshold) total++; else total--; } else if (!first_was_max_x && looking_for_max_x) { if (initial_x - min_x > threshold) total++; else total--; } if (first_was_max_y && looking_for_min_y) { if (max_y - initial_y > threshold) total++; else total--; } else if (!first_was_max_y && looking_for_max_y) { if (initial_y - min_y > threshold) total++; else total--; } return total; }