tesseract 3.04.01

C_OUTLINE Class Reference

#include <coutln.h>

Inheritance diagram for C_OUTLINE:
ELIST_LINK

List of all members.

Public Member Functions

 C_OUTLINE ()
 ~C_OUTLINE ()
BOOL8 flag (C_OUTLINE_FLAGS mask) const
void set_flag (C_OUTLINE_FLAGS mask, BOOL8 value)
C_OUTLINE_LIST * child ()
const TBOXbounding_box () const
void set_step (inT16 stepindex, inT8 stepdir)
void set_step (inT16 stepindex, DIR128 stepdir)
inT32 pathlength () const
DIR128 step_dir (int index) const
ICOORD step (int index) const
const ICOORDstart_pos () const
ICOORD position_at_index (int index) const
FCOORD sub_pixel_pos_at_index (const ICOORD &pos, int index) const
int direction_at_index (int index) const
int edge_strength_at_index (int index) const
int chain_code (int index) const
BOOL8 operator> (C_OUTLINE &other) const
C_OUTLINE::area

Compute the area of the outline.

inT32 area () const
C_OUTLINE::perimeter

Compute the perimeter of the outline and its first level children.

inT32 perimeter () const
C_OUTLINE::outer_area

Compute the area of the outline.

inT32 outer_area () const
C_OUTLINE::count_transitions

Compute the number of x and y maxes and mins in the outline.

Parameters:
thresholdwinding number on size
inT32 count_transitions (inT32 threshold)
C_OUTLINE::operator<
Returns:
TRUE if the left operand is inside the right one.
Parameters:
otherother outline
BOOL8 operator< (const C_OUTLINE &other) const
C_OUTLINE::winding_number
Returns:
the winding number of the outline around the given point.
Parameters:
pointpoint to wind around
inT16 winding_number (ICOORD testpt) const
inT16 turn_direction () const
C_OUTLINE::reverse

Reverse the direction of an outline.

void reverse ()
C_OUTLINE::move

Move C_OUTLINE by vector

Parameters:
vecvector to reposition OUTLINE by
void move (const ICOORD vec)
bool IsLegallyNested () const
void RemoveSmallRecursive (int min_size, C_OUTLINE_IT *it)
void ComputeEdgeOffsets (int threshold, Pix *pix)
void ComputeBinaryOffsets ()
void render (int left, int top, Pix *pix) const
void render_outline (int left, int top, Pix *pix) const
C_OUTLINE::plot

Draw the outline in the given colour.

Parameters:
windowwindow to draw in
colourcolour to draw in
void plot (ScrollView *window, ScrollView::Color colour) const
void plot_normed (const DENORM &denorm, ScrollView::Color colour, ScrollView *window) const

Static Public Member Functions

static C_OUTLINEdeep_copy (const C_OUTLINE *src)

Static Public Attributes

static const int kMaxOutlineLength = 16000

C_OUTLINE::C_OUTLINE

Constructor to build a C_OUTLINE from a rotation of a C_OUTLINE.

Parameters:
srclineoutline to rotate
rotationrotate to coord

 C_OUTLINE (CRACKEDGE *startpt, ICOORD bot_left, ICOORD top_right, inT16 length)
 C_OUTLINE (ICOORD startpt, DIR128 *new_steps, inT16 length)
 C_OUTLINE (C_OUTLINE *srcline, FCOORD rotation)
static void FakeOutline (const TBOX &box, C_OUTLINE_LIST *outlines)

C_OUTLINE::operator=

Assignment - deep copy data

Parameters:
sourceassign from this

C_OUTLINEoperator= (const C_OUTLINE &source)
static ICOORD chain_step (int chaindir)

Detailed Description

Definition at line 69 of file coutln.h.


Constructor & Destructor Documentation

C_OUTLINE::C_OUTLINE ( ) [inline]

Definition at line 71 of file coutln.h.

              {  //empty constructor
      steps = NULL;
      offsets = NULL;
    }
C_OUTLINE::C_OUTLINE ( CRACKEDGE startpt,
ICOORD  bot_left,
ICOORD  top_right,
inT16  length 
)

Definition at line 51 of file coutln.cpp.

    : box (bot_left, top_right), start (startpt->pos), offsets(NULL) {
  inT16 stepindex;               //index to step
  CRACKEDGE *edgept;             //current point

  stepcount = length;            //no of steps
  if (length == 0) {
    steps = NULL;
    return;
  }
                                 //get memory
  steps = (uinT8 *) alloc_mem (step_mem());
  memset(steps, 0, step_mem());
  edgept = startpt;

  for (stepindex = 0; stepindex < length; stepindex++) {
                                 //set compact step
    set_step (stepindex, edgept->stepdir);
    edgept = edgept->next;
  }
}
C_OUTLINE::C_OUTLINE ( ICOORD  startpt,
DIR128 new_steps,
inT16  length 
)

Definition at line 80 of file coutln.cpp.

 :start (startpt), offsets(NULL) {
  inT8 dirdiff;                  //direction difference
  DIR128 prevdir;                //previous direction
  DIR128 dir;                    //current direction
  DIR128 lastdir;                //dir of last step
  TBOX new_box;                   //easy bounding
  inT16 stepindex;               //index to step
  inT16 srcindex;                //source steps
  ICOORD pos;                    //current position

  pos = startpt;
  stepcount = length;            // No. of steps.
  ASSERT_HOST(length >= 0);
  steps = reinterpret_cast<uinT8*>(alloc_mem(step_mem()));  // Get memory.
  memset(steps, 0, step_mem());

  lastdir = new_steps[length - 1];
  prevdir = lastdir;
  for (stepindex = 0, srcindex = 0; srcindex < length;
  stepindex++, srcindex++) {
    new_box = TBOX (pos, pos);
    box += new_box;
                                 //copy steps
    dir = new_steps[srcindex];
    set_step(stepindex, dir);
    dirdiff = dir - prevdir;
    pos += step (stepindex);
    if ((dirdiff == 64 || dirdiff == -64) && stepindex > 0) {
      stepindex -= 2;            //cancel there-and-back
      prevdir = stepindex >= 0 ? step_dir (stepindex) : lastdir;
    }
    else
      prevdir = dir;
  }
  ASSERT_HOST (pos.x () == startpt.x () && pos.y () == startpt.y ());
  do {
    dirdiff = step_dir (stepindex - 1) - step_dir (0);
    if (dirdiff == 64 || dirdiff == -64) {
      start += step (0);
      stepindex -= 2;            //cancel there-and-back
      for (int i = 0; i < stepindex; ++i)
        set_step(i, step_dir(i + 1));
    }
  }
  while (stepindex > 1 && (dirdiff == 64 || dirdiff == -64));
  stepcount = stepindex;
  ASSERT_HOST (stepcount >= 4);
}
C_OUTLINE::C_OUTLINE ( C_OUTLINE srcline,
FCOORD  rotation 
)

Definition at line 142 of file coutln.cpp.

                                                        : offsets(NULL) {
  TBOX new_box;                   //easy bounding
  inT16 stepindex;               //index to step
  inT16 dirdiff;                 //direction change
  ICOORD pos;                    //current position
  ICOORD prevpos;                //previous dest point

  ICOORD destpos;                //destination point
  inT16 destindex;               //index to step
  DIR128 dir;                    //coded direction
  uinT8 new_step;

  stepcount = srcline->stepcount * 2;
  if (stepcount == 0) {
    steps = NULL;
    box = srcline->box;
    box.rotate(rotation);
    return;
  }
                                 //get memory
  steps = (uinT8 *) alloc_mem (step_mem());
  memset(steps, 0, step_mem());

  for (int iteration = 0; iteration < 2; ++iteration) {
    DIR128 round1 = iteration == 0 ? 32 : 0;
    DIR128 round2 = iteration != 0 ? 32 : 0;
    pos = srcline->start;
    prevpos = pos;
    prevpos.rotate (rotation);
    start = prevpos;
    box = TBOX (start, start);
    destindex = 0;
    for (stepindex = 0; stepindex < srcline->stepcount; stepindex++) {
      pos += srcline->step (stepindex);
      destpos = pos;
      destpos.rotate (rotation);
      //  tprintf("%i %i %i %i ", destpos.x(), destpos.y(), pos.x(), pos.y());
      while (destpos.x () != prevpos.x () || destpos.y () != prevpos.y ()) {
        dir = DIR128 (FCOORD (destpos - prevpos));
        dir += 64;                 //turn to step style
        new_step = dir.get_dir ();
        //  tprintf(" %i\n", new_step);
        if (new_step & 31) {
          set_step(destindex++, dir + round1);
          prevpos += step(destindex - 1);
          if (destindex < 2
            || ((dirdiff =
            step_dir (destindex - 1) - step_dir (destindex - 2)) !=
            -64 && dirdiff != 64)) {
            set_step(destindex++, dir + round2);
            prevpos += step(destindex - 1);
          } else {
            prevpos -= step(destindex - 1);
            destindex--;
            prevpos -= step(destindex - 1);
            set_step(destindex - 1, dir + round2);
            prevpos += step(destindex - 1);
          }
        }
        else {
          set_step(destindex++, dir);
          prevpos += step(destindex - 1);
        }
        while (destindex >= 2 &&
               ((dirdiff =
                 step_dir (destindex - 1) - step_dir (destindex - 2)) == -64 ||
                dirdiff == 64)) {
          prevpos -= step(destindex - 1);
          prevpos -= step(destindex - 2);
          destindex -= 2;        // Forget u turn
        }
        //ASSERT_HOST(prevpos.x() == destpos.x() && prevpos.y() == destpos.y());
        new_box = TBOX (destpos, destpos);
        box += new_box;
      }
    }
    ASSERT_HOST (destpos.x () == start.x () && destpos.y () == start.y ());
    dirdiff = step_dir (destindex - 1) - step_dir (0);
    while ((dirdiff == 64 || dirdiff == -64) && destindex > 1) {
      start += step (0);
      destindex -= 2;
      for (int i = 0; i < destindex; ++i)
        set_step(i, step_dir(i + 1));
      dirdiff = step_dir (destindex - 1) - step_dir (0);
    }
    if (destindex >= 4)
      break;
  }
  ASSERT_HOST(destindex <= stepcount);
  stepcount = destindex;
  destpos = start;
  for (stepindex = 0; stepindex < stepcount; stepindex++) {
    destpos += step (stepindex);
  }
  ASSERT_HOST (destpos.x () == start.x () && destpos.y () == start.y ());
}
C_OUTLINE::~C_OUTLINE ( ) [inline]

Definition at line 89 of file coutln.h.

                  {              //destructor
      if (steps != NULL)
        free_mem(steps);
      steps = NULL;
      delete [] offsets;
    }

Member Function Documentation

inT32 C_OUTLINE::area ( ) const

Definition at line 256 of file coutln.cpp.

                            {
  int stepindex;                 //current step
  inT32 total_steps;             //steps to do
  inT32 total;                   //total area
  ICOORD pos;                    //position of point
  ICOORD next_step;              //step to next pix
  // We aren't going to modify the list, or its contents, but there is
  // no const iterator.
  C_OUTLINE_IT it(const_cast<C_OUTLINE_LIST*>(&children));

  pos = start_pos ();
  total_steps = pathlength ();
  total = 0;
  for (stepindex = 0; stepindex < total_steps; stepindex++) {
                                 //all intersected
    next_step = step (stepindex);
    if (next_step.x () < 0)
      total += pos.y ();
    else if (next_step.x () > 0)
      total -= pos.y ();
    pos += next_step;
  }
  for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ())
    total += it.data ()->area ();//add areas of children

  return total;
}
const TBOX& C_OUTLINE::bounding_box ( ) const [inline]

Definition at line 111 of file coutln.h.

                                     {
      return box;
    }
int C_OUTLINE::chain_code ( int  index) const [inline]

Definition at line 193 of file coutln.h.

                                    {  // index of step
      return (steps[index / 4] >> (index % 4 * 2)) & STEP_MASK;
    }
ICOORD C_OUTLINE::chain_step ( int  chaindir) [static]

Definition at line 1067 of file coutln.cpp.

                                         {
  return step_coords[chaindir % 4];
}
C_OUTLINE_LIST* C_OUTLINE::child ( ) [inline]

Definition at line 106 of file coutln.h.

                            {  //get child list
      return &children;
    }
void C_OUTLINE::ComputeBinaryOffsets ( )

Adds sub-pixel resolution EdgeOffsets for the outline using only a binary image source.

Runs a sliding window of 5 edge steps over the outline, maintaining a count of the number of steps in each of the 4 directions in the window, and a sum of the x or y position of each step (as appropriate to its direction.) Ignores single-count steps EXCEPT the sharp U-turn and smoothes out the perpendicular direction. Eg

 * ___              ___       Chain code from the left:
 *    |___    ___   ___|      222122212223221232223000
 *        |___|  |_|          Corresponding counts of each direction:
 *                          0   00000000000000000123
 *                          1   11121111001111100000
 *                          2   44434443443333343321
 *                          3   00000001111111112111
 * Count of direction at center 41434143413313143313
 * Step gets used?              YNYYYNYYYNYYNYNYYYyY (y= U-turn exception)
 * Path redrawn showing only the used points:
 * ___              ___
 *     ___    ___   ___|
 *         ___    _
 * 

Sub-pixel edge position cannot be shown well with ASCII-art, but each horizontal step's y position is the mean of the y positions of the steps in the same direction in the sliding window, which makes a much smoother outline, without losing important detail.

Definition at line 851 of file coutln.cpp.

                                     {
  delete [] offsets;
  offsets = new EdgeOffset[stepcount];
  // Count of the number of steps in each direction in the sliding window.
  int dir_counts[4];
  // Sum of the positions (y for a horizontal step, x for vertical) in each
  // direction in the sliding window.
  int pos_totals[4];
  memset(dir_counts, 0, sizeof(dir_counts));
  memset(pos_totals, 0, sizeof(pos_totals));
  ICOORD pos = start;
  ICOORD tail_pos = pos;
  // tail_pos is the trailing position, with the next point to be lost from
  // the window.
  tail_pos -= step(stepcount - 1);
  tail_pos -= step(stepcount - 2);
  // head_pos is the leading position, with the next point to be added to the
  // window.
  ICOORD head_pos = tail_pos;
  // Set up the initial window with 4 points in [-2, 2)
  for (int s = -2; s < 2; ++s) {
    increment_step(s, 1, &head_pos, dir_counts, pos_totals);
  }
  for (int s = 0; s < stepcount; pos += step(s++)) {
    // At step s, s in in the middle of [s-2, s+2].
    increment_step(s + 2, 1, &head_pos, dir_counts, pos_totals);
    int dir_index = chain_code(s);
    ICOORD step_vec = step(s);
    int best_diff = 0;
    int offset = 0;
    // Use only steps that have a count of >=2 OR the strong U-turn with a
    // single d and 2 at d-1 and 2 at d+1 (mod 4).
    if (dir_counts[dir_index] >= 2 || (dir_counts[dir_index] == 1 &&
        dir_counts[Modulo(dir_index - 1, 4)] == 2 &&
        dir_counts[Modulo(dir_index + 1, 4)] == 2)) {
      // Valid step direction.
      best_diff = dir_counts[dir_index];
      int edge_pos = step_vec.x() == 0 ? pos.x() : pos.y();
      // The offset proposes that the actual step should be positioned at
      // the mean position of the steps in the window of the same direction.
      // See ASCII art above.
      offset = pos_totals[dir_index] - best_diff * edge_pos;
    }
    offsets[s].offset_numerator =
        static_cast<inT8>(ClipToRange(offset, -MAX_INT8, MAX_INT8));
    offsets[s].pixel_diff = static_cast<uinT8>(ClipToRange(best_diff, 0 ,
                                                           MAX_UINT8));
    // The direction is just the vector from start to end of the window.
    FCOORD direction(head_pos.x() - tail_pos.x(), head_pos.y() - tail_pos.y());
    offsets[s].direction = direction.to_direction();
    increment_step(s - 2, -1, &tail_pos, dir_counts, pos_totals);
  }
}
void C_OUTLINE::ComputeEdgeOffsets ( int  threshold,
Pix *  pix 
)

Adds sub-pixel resolution EdgeOffsets for the outline if the supplied pix is 8-bit. Does nothing otherwise. Operation: Consider the following near-horizontal line:

 *   _________
 *            |________
 *                     |________
 * 

At *every* position along this line, the gradient direction will be close to vertical. Extrapoaltion/interpolation of the position of the threshold that was used to binarize the image gives a more precise vertical position for each horizontal step, and the conflict in step direction and gradient direction can be used to ignore the vertical steps.

Definition at line 734 of file coutln.cpp.

                                                          {
  if (pixGetDepth(pix) != 8) return;
  const l_uint32* data = pixGetData(pix);
  int wpl = pixGetWpl(pix);
  int width = pixGetWidth(pix);
  int height = pixGetHeight(pix);
  bool negative = flag(COUT_INVERSE);
  delete [] offsets;
  offsets = new EdgeOffset[stepcount];
  ICOORD pos = start;
  ICOORD prev_gradient;
  ComputeGradient(data, wpl, pos.x(), height - pos.y(), width, height,
                  &prev_gradient);
  for (int s = 0; s < stepcount; ++s) {
    ICOORD step_vec = step(s);
    TPOINT pt1(pos);
    pos += step_vec;
    TPOINT pt2(pos);
    ICOORD next_gradient;
    ComputeGradient(data, wpl, pos.x(), height - pos.y(), width, height,
                    &next_gradient);
    // Use the sum of the prev and next as the working gradient.
    ICOORD gradient = prev_gradient + next_gradient;
    // best_diff will be manipulated to be always positive.
    int best_diff = 0;
    // offset will be the extrapolation of the location of the greyscale
    // threshold from the edge with the largest difference, relative to the
    // location of the binary edge.
    int offset = 0;
    if (pt1.y == pt2.y && abs(gradient.y()) * 2 >= abs(gradient.x())) {
      // Horizontal step. diff_sign == 1 indicates black above.
      int diff_sign = (pt1.x > pt2.x) == negative ? 1 : -1;
      int x = MIN(pt1.x, pt2.x);
      int y = height - pt1.y;
      int best_sum = 0;
      int best_y = y;
      EvaluateVerticalDiff(data, wpl, diff_sign, x, y, height,
                           &best_diff, &best_sum, &best_y);
      // Find the strongest edge.
      int test_y = y;
      do {
        ++test_y;
      } while (EvaluateVerticalDiff(data, wpl, diff_sign, x, test_y, height,
                                    &best_diff, &best_sum, &best_y));
      test_y = y;
      do {
        --test_y;
      } while (EvaluateVerticalDiff(data, wpl, diff_sign, x, test_y, height,
                                    &best_diff, &best_sum, &best_y));
      offset = diff_sign * (best_sum / 2 - threshold) +
          (y - best_y) * best_diff;
    } else if (pt1.x == pt2.x && abs(gradient.x()) * 2 >= abs(gradient.y())) {
      // Vertical step. diff_sign == 1 indicates black on the left.
      int diff_sign = (pt1.y > pt2.y) == negative ? 1 : -1;
      int x = pt1.x;
      int y = height - MAX(pt1.y, pt2.y);
      const l_uint32* line = pixGetData(pix) + y * wpl;
      int best_sum = 0;
      int best_x = x;
      EvaluateHorizontalDiff(line, diff_sign, x, width,
                             &best_diff, &best_sum, &best_x);
      // Find the strongest edge.
      int test_x = x;
      do {
        ++test_x;
      } while (EvaluateHorizontalDiff(line, diff_sign, test_x, width,
                                      &best_diff, &best_sum, &best_x));
      test_x = x;
      do {
        --test_x;
      } while (EvaluateHorizontalDiff(line, diff_sign, test_x, width,
                                      &best_diff, &best_sum, &best_x));
      offset = diff_sign * (threshold - best_sum / 2) +
          (best_x - x) * best_diff;
    }
    offsets[s].offset_numerator =
        static_cast<inT8>(ClipToRange(offset, -MAX_INT8, MAX_INT8));
    offsets[s].pixel_diff = static_cast<uinT8>(ClipToRange(best_diff, 0 ,
                                                           MAX_UINT8));
    if (negative) gradient = -gradient;
    // Compute gradient angle quantized to 256 directions, rotated by 64 (pi/2)
    // to convert from gradient direction to edge direction.
    offsets[s].direction =
        Modulo(FCOORD::binary_angle_plus_pi(gradient.angle()) + 64, 256);
    prev_gradient = next_gradient;
  }
}
inT32 C_OUTLINE::count_transitions ( inT32  threshold)

Definition at line 343 of file coutln.cpp.

                                                  {
  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;
}
static C_OUTLINE* C_OUTLINE::deep_copy ( const C_OUTLINE src) [inline, static]

Definition at line 259 of file coutln.h.

                                                      {
      C_OUTLINE* outline = new C_OUTLINE;
      *outline = *src;
      return outline;
    }
int C_OUTLINE::direction_at_index ( int  index) const [inline]

Definition at line 176 of file coutln.h.

                                            {
      if (offsets != NULL && offsets[index].pixel_diff > 0)
        return offsets[index].direction;
      return -1;
    }
int C_OUTLINE::edge_strength_at_index ( int  index) const [inline]

Definition at line 185 of file coutln.h.

                                                {
      if (offsets != NULL)
        return offsets[index].pixel_diff;
      return 1;
    }
void C_OUTLINE::FakeOutline ( const TBOX box,
C_OUTLINE_LIST *  outlines 
) [static]

Definition at line 240 of file coutln.cpp.

                                                                     {
  C_OUTLINE_IT ol_it(outlines);
  // Make a C_OUTLINE from the bounds. This is a bit of a hack,
  // as there is no outline, just a bounding box, but it works nicely.
  CRACKEDGE start;
  start.pos = box.topleft();
  C_OUTLINE* outline = new C_OUTLINE(&start, box.topleft(), box.botright(), 0);
  ol_it.add_to_end(outline);
}
BOOL8 C_OUTLINE::flag ( C_OUTLINE_FLAGS  mask) const [inline]

Definition at line 96 of file coutln.h.

                                           {  //flag to test
      return flags.bit (mask);
    }
bool C_OUTLINE::IsLegallyNested ( ) const

Returns true if *this and its children are legally nested. The outer area of a child should have the opposite sign to the parent. If not, it means we have discarded an outline in between (probably due to excessive length).

Definition at line 613 of file coutln.cpp.

                                      {
  if (stepcount == 0) return true;
  int parent_area = outer_area();
  // We aren't going to modify the list, or its contents, but there is
  // no const iterator.
  C_OUTLINE_IT child_it(const_cast<C_OUTLINE_LIST*>(&children));
  for (child_it.mark_cycle_pt(); !child_it.cycled_list(); child_it.forward()) {
    const C_OUTLINE* child = child_it.data();
    if (child->outer_area() * parent_area > 0 || !child->IsLegallyNested())
      return false;
  }
  return true;
}
void C_OUTLINE::move ( const ICOORD  vec)

Definition at line 597 of file coutln.cpp.

                                     {
  C_OUTLINE_IT it(&children);  // iterator

  box.move (vec);
  start += vec;

  for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ())
    it.data ()->move (vec);      // move child outlines
}
BOOL8 C_OUTLINE::operator< ( const C_OUTLINE other) const

Definition at line 471 of file coutln.cpp.

{
  inT16 count = 0;               //winding count
  ICOORD pos;                    //position of point
  inT32 stepindex;               //index to cstep

  if (!box.overlap (other.box))
    return FALSE;                //can't be contained
  if (stepcount == 0)
    return other.box.contains(this->box);

  pos = start;
  for (stepindex = 0; stepindex < stepcount
    && (count = other.winding_number (pos)) == INTERSECTING; stepindex++)
    pos += step (stepindex);     //try all points
  if (count == INTERSECTING) {
                                 //all intersected
    pos = other.start;
    for (stepindex = 0; stepindex < other.stepcount
      && (count = winding_number (pos)) == INTERSECTING; stepindex++)
                                 //try other way round
      pos += other.step (stepindex);
    return count == INTERSECTING || count == 0;
  }
  return count != 0;
}
C_OUTLINE & C_OUTLINE::operator= ( const C_OUTLINE source)

Definition at line 1027 of file coutln.cpp.

                                                          {
  box = source.box;
  start = source.start;
  if (steps != NULL)
    free_mem(steps);
  stepcount = source.stepcount;
  steps = (uinT8 *) alloc_mem (step_mem());
  memmove (steps, source.steps, step_mem());
  if (!children.empty ())
    children.clear ();
  children.deep_copy(&source.children, &deep_copy);
  delete [] offsets;
  if (source.offsets != NULL) {
    offsets = new EdgeOffset[stepcount];
    memcpy(offsets, source.offsets, stepcount * sizeof(*offsets));
  } else {
    offsets = NULL;
  }
  return *this;
}
BOOL8 C_OUTLINE::operator> ( C_OUTLINE other) const [inline]

Definition at line 205 of file coutln.h.

    {
      return other < *this;      //use the < to do it
    }
inT32 C_OUTLINE::outer_area ( ) const

Definition at line 310 of file coutln.cpp.

                                  {
  int stepindex;                 //current step
  inT32 total_steps;             //steps to do
  inT32 total;                   //total area
  ICOORD pos;                    //position of point
  ICOORD next_step;              //step to next pix

  pos = start_pos ();
  total_steps = pathlength ();
  if (total_steps == 0)
    return box.area();
  total = 0;
  for (stepindex = 0; stepindex < total_steps; stepindex++) {
                                 //all intersected
    next_step = step (stepindex);
    if (next_step.x () < 0)
      total += pos.y ();
    else if (next_step.x () > 0)
      total -= pos.y ();
    pos += next_step;
  }

  return total;
}
inT32 C_OUTLINE::pathlength ( ) const [inline]

Definition at line 133 of file coutln.h.

                             {  //get path length
      return stepcount;
    }
inT32 C_OUTLINE::perimeter ( ) const

Definition at line 290 of file coutln.cpp.

                                 {
  inT32 total_steps;             // Return value.
  // We aren't going to modify the list, or its contents, but there is
  // no const iterator.
  C_OUTLINE_IT it(const_cast<C_OUTLINE_LIST*>(&children));

  total_steps = pathlength();
  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward())
    total_steps += it.data()->pathlength();  // Add perimeters of children.

  return total_steps;
}
void C_OUTLINE::plot ( ScrollView window,
ScrollView::Color  colour 
) const

Definition at line 957 of file coutln.cpp.

                                                   {
  inT16 stepindex;               // index to cstep
  ICOORD pos;                    // current position
  DIR128 stepdir;                // direction of step

  pos = start;                   // current position
  window->Pen(colour);
  if (stepcount == 0) {
    window->Rectangle(box.left(), box.top(), box.right(), box.bottom());
    return;
  }
  window->SetCursor(pos.x(), pos.y());

  stepindex = 0;
  while (stepindex < stepcount) {
    pos += step(stepindex);    // step to next
    stepdir = step_dir(stepindex);
    stepindex++;               // count steps
    // merge straight lines
    while (stepindex < stepcount &&
           stepdir.get_dir() == step_dir(stepindex).get_dir()) {
      pos += step(stepindex);
      stepindex++;
    }
    window->DrawTo(pos.x(), pos.y());
  }
}
void C_OUTLINE::plot_normed ( const DENORM denorm,
ScrollView::Color  colour,
ScrollView window 
) const

Draws the outline in the given colour, normalized using the given denorm, making use of sub-pixel accurate information if available.

Definition at line 990 of file coutln.cpp.

                                                      {
  window->Pen(colour);
  if (stepcount == 0) {
    window->Rectangle(box.left(), box.top(), box.right(), box.bottom());
    return;
  }
  const DENORM* root_denorm = denorm.RootDenorm();
  ICOORD pos = start;                   // current position
  FCOORD f_pos = sub_pixel_pos_at_index(pos, 0);
  FCOORD pos_normed;
  denorm.NormTransform(root_denorm, f_pos, &pos_normed);
  window->SetCursor(IntCastRounded(pos_normed.x()),
                    IntCastRounded(pos_normed.y()));
  for (int s = 0; s < stepcount; pos += step(s++)) {
    int edge_weight = edge_strength_at_index(s);
    if (edge_weight == 0) {
      // This point has conflicting gradient and step direction, so ignore it.
      continue;
    }
    FCOORD f_pos = sub_pixel_pos_at_index(pos, s);
    FCOORD pos_normed;
    denorm.NormTransform(root_denorm, f_pos, &pos_normed);
    window->DrawTo(IntCastRounded(pos_normed.x()),
                   IntCastRounded(pos_normed.y()));
  }
}
ICOORD C_OUTLINE::position_at_index ( int  index) const [inline]

Definition at line 151 of file coutln.h.

                                              {
      ICOORD pos = start;
      for (int i = 0; i < index; ++i)
        pos += step(i);
      return pos;
    }
void C_OUTLINE::RemoveSmallRecursive ( int  min_size,
C_OUTLINE_IT *  it 
)

If this outline is smaller than the given min_size, delete this and remove from its list, via *it, after checking that *it points to this. Otherwise, if any children of this are too small, delete them. On entry, *it must be an iterator pointing to this. If this gets deleted then this is extracted from *it, so an iteration can continue.

Parameters:
min_sizeminimum size for outline
itoutline iterator

Definition at line 636 of file coutln.cpp.

                                                                   {
  if (box.width() < min_size || box.height() < min_size) {
    ASSERT_HOST(this == it->data());
    delete it->extract();  // Too small so get rid of it and any children.
  } else if (!children.empty()) {
    // Search the children of this, deleting any that are too small.
    C_OUTLINE_IT child_it(&children);
    for (child_it.mark_cycle_pt(); !child_it.cycled_list();
         child_it.forward()) {
      C_OUTLINE* child = child_it.data();
      child->RemoveSmallRecursive(min_size, &child_it);
    }
  }
}
void C_OUTLINE::render ( int  left,
int  top,
Pix *  pix 
) const

Renders the outline to the given pix, with left and top being the coords of the upper-left corner of the pix.

Definition at line 909 of file coutln.cpp.

                                                        {
  ICOORD pos = start;
  for (int stepindex = 0; stepindex < stepcount; ++stepindex) {
    ICOORD next_step = step(stepindex);
    if (next_step.y() < 0) {
      pixRasterop(pix, 0, top - pos.y(), pos.x() - left, 1,
                  PIX_NOT(PIX_DST), NULL, 0, 0);
    } else if (next_step.y() > 0) {
      pixRasterop(pix, 0, top - pos.y() - 1, pos.x() - left, 1,
                  PIX_NOT(PIX_DST), NULL, 0, 0);
    }
    pos += next_step;
  }
}
void C_OUTLINE::render_outline ( int  left,
int  top,
Pix *  pix 
) const

Renders just the outline to the given pix (no fill), with left and top being the coords of the upper-left corner of the pix.

Parameters:
leftcoord
topcoord
pixthe pix to outline

Definition at line 931 of file coutln.cpp.

                                                                {
  ICOORD pos = start;
  for (int stepindex = 0; stepindex < stepcount; ++stepindex) {
    ICOORD next_step = step(stepindex);
    if (next_step.y() < 0) {
      pixSetPixel(pix, pos.x() - left, top - pos.y(), 1);
    } else if (next_step.y() > 0) {
      pixSetPixel(pix, pos.x() - left - 1, top - pos.y() - 1, 1);
    } else if (next_step.x() < 0) {
      pixSetPixel(pix, pos.x() - left - 1, top - pos.y(), 1);
    } else if (next_step.x() > 0) {
      pixSetPixel(pix, pos.x() - left, top - pos.y() - 1, 1);
    }
    pos += next_step;
  }
}
void C_OUTLINE::reverse ( )

Definition at line 573 of file coutln.cpp.

                        {  //reverse drection
  DIR128 halfturn = MODULUS / 2; //amount to shift
  DIR128 stepdir;                //direction of step
  inT16 stepindex;               //index to cstep
  inT16 farindex;                //index to other side
  inT16 halfsteps;               //half of stepcount

  halfsteps = (stepcount + 1) / 2;
  for (stepindex = 0; stepindex < halfsteps; stepindex++) {
    farindex = stepcount - stepindex - 1;
    stepdir = step_dir (stepindex);
    set_step (stepindex, step_dir (farindex) + halfturn);
    set_step (farindex, stepdir + halfturn);
  }
}
void C_OUTLINE::set_flag ( C_OUTLINE_FLAGS  mask,
BOOL8  value 
) [inline]

Definition at line 100 of file coutln.h.

                               {         //value to set
      flags.set_bit (mask, value);
    }
void C_OUTLINE::set_step ( inT16  stepindex,
inT8  stepdir 
) [inline]

Definition at line 114 of file coutln.h.

                                {     //chain code
      int shift = stepindex%4 * 2;
      uinT8 mask = 3 << shift;
      steps[stepindex/4] = ((stepdir << shift) & mask) |
                           (steps[stepindex/4] & ~mask);
      //squeeze 4 into byte
    }
void C_OUTLINE::set_step ( inT16  stepindex,
DIR128  stepdir 
) [inline]

Definition at line 123 of file coutln.h.

                                  {   //direction
                                 //clean it
      inT8 chaindir = stepdir.get_dir() >> (DIRBITS - 2);
                                 //difference
      set_step(stepindex, chaindir);
      //squeeze 4 into byte
    }
const ICOORD& C_OUTLINE::start_pos ( ) const [inline]

Definition at line 146 of file coutln.h.

                                    {
      return start;
    }
ICOORD C_OUTLINE::step ( int  index) const [inline]

Definition at line 142 of file coutln.h.

                                 { // index of step
      return step_coords[chain_code(index)];
    }
DIR128 C_OUTLINE::step_dir ( int  index) const [inline]

Definition at line 137 of file coutln.h.

                                     {
      return DIR128((inT16)(((steps[index/4] >> (index%4 * 2)) & STEP_MASK) <<
                      (DIRBITS - 2)));
    }
FCOORD C_OUTLINE::sub_pixel_pos_at_index ( const ICOORD pos,
int  index 
) const [inline]

Definition at line 161 of file coutln.h.

                                                                      {
      const ICOORD& step_to_next(step(index));
      FCOORD f_pos(pos.x() + step_to_next.x() / 2.0f,
                   pos.y() + step_to_next.y() / 2.0f);
      if (offsets != NULL && offsets[index].pixel_diff > 0) {
        float offset = offsets[index].offset_numerator;
        offset /= offsets[index].pixel_diff;
        if (step_to_next.x() != 0)
          f_pos.set_y(f_pos.y() + offset);
        else
          f_pos.set_x(f_pos.x() + offset);
      }
      return f_pos;
    }
inT16 C_OUTLINE::turn_direction ( ) const

C_OUTLINE::turn_direction

Returns:
the sum direction delta of the outline.

Definition at line 544 of file coutln.cpp.

                                      {  //winding number
  DIR128 prevdir;                //previous direction
  DIR128 dir;                    //current direction
  inT16 stepindex;               //index to cstep
  inT8 dirdiff;                  //direction difference
  inT16 count;                   //winding count

  if (stepcount == 0)
    return 128;
  count = 0;
  prevdir = step_dir (stepcount - 1);
  for (stepindex = 0; stepindex < stepcount; stepindex++) {
    dir = step_dir (stepindex);
    dirdiff = dir - prevdir;
    ASSERT_HOST (dirdiff == 0 || dirdiff == 32 || dirdiff == -32);
    count += dirdiff;
    prevdir = dir;
  }
  ASSERT_HOST (count == 128 || count == -128);
  return count;                  //winding number
}
inT16 C_OUTLINE::winding_number ( ICOORD  testpt) const

Definition at line 506 of file coutln.cpp.

                                                  {
  inT16 stepindex;               //index to cstep
  inT16 count;                   //winding count
  ICOORD vec;                    //to current point
  ICOORD stepvec;                //step vector
  inT32 cross;                   //cross product

  vec = start - point;           //vector to it
  count = 0;
  for (stepindex = 0; stepindex < stepcount; stepindex++) {
    stepvec = step (stepindex);  //get the step
                                 //crossing the line
    if (vec.y () <= 0 && vec.y () + stepvec.y () > 0) {
      cross = vec * stepvec;     //cross product
      if (cross > 0)
        count++;                 //crossing right half
      else if (cross == 0)
        return INTERSECTING;     //going through point
    }
    else if (vec.y () > 0 && vec.y () + stepvec.y () <= 0) {
      cross = vec * stepvec;
      if (cross < 0)
        count--;                 //crossing back
      else if (cross == 0)
        return INTERSECTING;     //illegal
    }
    vec += stepvec;              //sum vectors
  }
  return count;                  //winding number
}

Member Data Documentation

const int C_OUTLINE::kMaxOutlineLength = 16000 [static]

Definition at line 271 of file coutln.h.


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines