Back to index

tetex-bin  3.0
Defines | Functions | Variables
hints.c File Reference
#include <stdio.h>
#include "types.h"
#include "objects.h"
#include "spaces.h"
#include "paths.h"
#include "regions.h"
#include "hints.h"

Go to the source code of this file.

Defines

#define MAXLABEL   20
#define ODD(x)   (((int)(x)) & 01)
#define FPFLOOR(fp)   TOFRACTPEL((fp) >> FRACTBITS)
#define FPROUND(fp)   FPFLOOR((fp) + FPHALF)
#define ISTOP(flag)   ((flag)&0x20)
#define ISBOTTOM(flag)   ((flag)&0x10)
#define ISLEFT(flag)   ((flag)&0x08)
#define XofY(edge, y)   edge->xvalues[y - edge->ymin]
#define findXofY(edge, y)   ((y < edge->ymin || y >= edge->ymax) ? SearchXofY(edge, y) : XofY(edge, y))
#define ISBREAK(top, bot)   (top->ymax != bot->ymin)
#define BLACKABOVE   -1
#define BLACKBELOW   +1
#define NONE   0
#define IsValidPel(j)   (j!=MINPEL)
#define WeAreAtTop(e, i)   (ISTOP(e->flag) && e->ymin == i)
#define WeAreAtBottom(e, i)   (ISBOTTOM(e->flag) && e->ymax-1 == i)
#define WeAreInMiddle(e, i)   ((!ISTOP(e->flag) && !ISBOTTOM(e->flag))||(i < e->ymax-1 && i > e->ymin))
#define SAMESWATH(e1, e2)   (e1->ymin == e2->ymin)

Functions

void InitHints ()
void CloseHints (struct fractpoint *hintP)
static void ComputeHint (struct hintsegment *hP, fractpel currX, fractpel currY, struct fractpoint *hintP)
void ProcessHint (struct hintsegment *hP, fractpel currX, fractpel currY, struct fractpoint *hintP)
static pel SearchXofY (struct edgelist *edge, pel y)
static int ImpliedHorizontalLine (struct edgelist *e1, struct edgelist *e2, int y)
static void FixSubPaths (struct region *R)
static struct edgelistbefore ()
static void DumpSubPaths (struct edgelist *anchor)
static struct edgelistbefore (struct edgelist *e)
static void writeXofY (struct edgelist *e, int y, int x)
static void CollapseWhiteRun (struct edgelist *anchor, pel yblack, struct edgelist *left, struct edgelist *right, pel ywhite)
void ApplyContinuity (struct region *R)

Variables

struct {
int inuse
int computed
oldHint [MAXLABEL]

Define Documentation

#define BLACKABOVE   -1

Definition at line 425 of file hints.c.

#define BLACKBELOW   +1

Definition at line 426 of file hints.c.

#define findXofY (   edge,
  y 
)    ((y < edge->ymin || y >= edge->ymax) ? SearchXofY(edge, y) : XofY(edge, y))

Definition at line 356 of file hints.c.

#define FPFLOOR (   fp)    TOFRACTPEL((fp) >> FRACTBITS)

Definition at line 84 of file hints.c.

#define FPROUND (   fp)    FPFLOOR((fp) + FPHALF)

Definition at line 85 of file hints.c.

#define ISBOTTOM (   flag)    ((flag)&0x10)

Definition at line 333 of file hints.c.

#define ISBREAK (   top,
  bot 
)    (top->ymax != bot->ymin)

Definition at line 413 of file hints.c.

#define ISLEFT (   flag)    ((flag)&0x08)

Definition at line 338 of file hints.c.

#define ISTOP (   flag)    ((flag)&0x20)

Definition at line 332 of file hints.c.

#define IsValidPel (   j)    (j!=MINPEL)

Definition at line 740 of file hints.c.

#define MAXLABEL   20

Definition at line 76 of file hints.c.

#define NONE   0

Definition at line 427 of file hints.c.

#define ODD (   x)    (((int)(x)) & 01)

Definition at line 83 of file hints.c.

#define SAMESWATH (   e1,
  e2 
)    (e1->ymin == e2->ymin)

Definition at line 774 of file hints.c.

#define WeAreAtBottom (   e,
  i 
)    (ISBOTTOM(e->flag) && e->ymax-1 == i)

Definition at line 767 of file hints.c.

#define WeAreAtTop (   e,
  i 
)    (ISTOP(e->flag) && e->ymin == i)

Definition at line 766 of file hints.c.

#define WeAreInMiddle (   e,
  i 
)    ((!ISTOP(e->flag) && !ISBOTTOM(e->flag))||(i < e->ymax-1 && i > e->ymin))

Definition at line 768 of file hints.c.

#define XofY (   edge,
  y 
)    edge->xvalues[y - edge->ymin]

Definition at line 347 of file hints.c.


Function Documentation

void ApplyContinuity ( struct region R)

Definition at line 857 of file hints.c.

{
  struct edgelist *left;
  struct edgelist *right;
  struct edgelist *edge,*e2;
  pel rightXabove,rightXbelow,leftXabove,leftXbelow;
  pel leftX,rightX;
  int i;
  long edgecnt = 0;
  
  fractpel xavrg = 0;
  LONG newcenter,abovecenter,belowcenter;

  
  FixSubPaths(R);
  if ( RegionDebug >= 3)
    DumpSubPaths(R->anchor);
  left = R->anchor;

  /* loop through and do all of the easy checking. ( no tops or bottoms) */
  while(VALIDEDGE(left)) {
    right = left->link;
    for(i=left->ymin;i<left->ymax;++i) {
      leftX       = findXofY(left,i);
      rightX      = findXofY(right,i);
      leftXbelow  = findXofY(left,i+1);
      rightXbelow = findXofY(right,i+1);
      if(rightX <= leftX) {

       /* then, we have a break in a near vertical line */
       leftXabove  = findXofY(left,i-1);
       rightXabove = findXofY(right,i-1);
       /* Check above current scanline */
       if ( IsValidPel(leftXabove) && IsValidPel(rightXabove) ) {
         abovecenter = leftXabove + rightXabove;
       }
       else { 
         /* We are at the top. We can assume that the current edge list is just started
            --> Inspect the stored start fractpel values in order to decide about
            to which side to extend. -->
            Compute arithmetic average between left and right edge at high resolution */
         xavrg        = ((left->fpx1 + right->fpx1) >> 1);
         /* round down to get left (not nearest!) and get right edge by adding one pel. */
         leftXabove   = (xavrg >> FRACTBITS);
         rightXabove  = leftXabove + 1;
         abovecenter  = leftXabove + rightXabove;
         belowcenter  = leftXabove + rightXabove;
       }

       /* Check below current scanline */
       if ( IsValidPel(leftXbelow) && IsValidPel(rightXbelow) ) {
         belowcenter  = leftXbelow + rightXbelow;
       }
       else { 
         /* We are at the bottom. We can assume that the current edge list terminates here
            --> Inspect the stored end fractpel values in order to decide about
            to which side to extend. -->
            Compute arithmetic average between left and right edge at high resolution */
         xavrg        = ((left->fpx2 + right->fpx2) >> 1);
         /* round down to get left (not nearest!) and get right edge by adding one pel. */
         leftXbelow   = (xavrg >> FRACTBITS);
         rightXbelow  = leftXbelow + 1;
         abovecenter  = leftXbelow + rightXbelow;
         belowcenter  = leftXbelow + rightXbelow;
       }

       newcenter = abovecenter + belowcenter;

       if( newcenter > 4*leftX ) {
         rightX = rightX + 1;
         writeXofY(right,i,rightX);
       }
       else if( newcenter < 4*leftX) {
         leftX = leftX - 1;
         writeXofY(left,i,leftX);
       }
       else {
         rightX = rightX + 1;
         writeXofY(right,i,rightX);
       }
       
       if ( rightX > R->xmax ) {
         R->xmax = rightX;
       }
       if ( leftX < R->xmin ) {
         R->xmin = leftX;
       }
      }
      if( !WeAreAtBottom(left,i) && (leftXbelow>=rightX)) {
       /* then we have a break in a near horizontal line in the middle */
       writeXofY(right,i,leftXbelow);
      }
      if( !WeAreAtBottom(right,i) && (leftX >=rightXbelow)) {
       /* then we have a break in a near horizontal line in the middle */
       writeXofY(left,i,rightXbelow);
      }
    }
    left = right->link;
    ++edgecnt;
  }
  
  /*
    There may be "implied horizontal lines" between edges that have
    implications for continuity.  This loop looks for white runs that
    have implied horizontal lines on the top or bottom, and calls
    CollapseWhiteRuns to check and fix any continuity problems from
    them.
  */
  for (edge = R->anchor; VALIDEDGE(edge); edge = edge->link) {
    if ((!ISTOP(edge->flag) && !ISBOTTOM(edge->flag)) || ISLEFT(edge->flag))
      continue;  /* at some future date we may want left edge logic here too */
    for (e2 = edge->link; VALIDEDGE(e2) && SAMESWATH(edge,e2); e2 = e2->link) {
      if (ISTOP(e2->flag) && ISTOP(edge->flag)
         && NONE != ImpliedHorizontalLine(edge,e2,edge->ymin)) {
       if (ISLEFT(e2->flag))
         CollapseWhiteRun(R->anchor, edge->ymin-1,
                        edge, e2, edge->ymin);
      }
      if (ISBOTTOM(e2->flag) && ISBOTTOM(edge->flag)
         && NONE != ImpliedHorizontalLine(edge,e2, edge->ymax)) {
       if (ISLEFT(e2->flag))
         CollapseWhiteRun(R->anchor, edge->ymax,
                        edge, e2, edge->ymax-1);
      }
    }
  }
}

Here is the call graph for this function:

static struct edgelist* before ( ) [static, read]

Here is the caller graph for this function:

static struct edgelist* before ( struct edgelist e) [static, read]

Definition at line 718 of file hints.c.

{
       struct edgelist *r;
       for (r = e->subpath; r->subpath != e; r = r->subpath) { ; }
       return(r);
}
void CloseHints ( struct fractpoint hintP)

Definition at line 102 of file hints.c.

{
  int i;
 
  for (i = 0; i < MAXLABEL; i++)
    {
    if (oldHint[i].inuse)
      {
      hintP->x -= oldHint[i].hint.x;
      hintP->y -= oldHint[i].hint.y;
 
      oldHint[i].inuse = FALSE;
 
      IfTrace3((HintDebug > 1),"  Hint %d was open, hint=(%d,%d)\n",
                i, hintP->x, hintP->y);
      }
    }
}
static void CollapseWhiteRun ( struct edgelist anchor,
pel  yblack,
struct edgelist left,
struct edgelist right,
pel  ywhite 
) [static]

Definition at line 786 of file hints.c.

{
       struct edgelist *edge;
       struct edgelist *swathstart = anchor;
       register pel x;
 
       if (XofY(left, ywhite) >= XofY(right, ywhite))
               return;
/*
Find the swath with 'yblack'.  If we don't find it, completely collapse
the white run and return:
*/
       while (VALIDEDGE(swathstart)) {
               if (yblack < swathstart->ymin)  {
                      writeXofY(left, ywhite, XofY(right, ywhite));
                      return;
               }
               if (yblack < swathstart->ymax) break;
               swathstart = swathstart->link->link;
       }
       if(!VALIDEDGE(swathstart)) {
               writeXofY(left, ywhite, XofY(right, ywhite));
               return;
       }
/*
Now we are in the swath that contains 'y', the reference line above
or below that we are trying to maintain continuity with.  If black
in this line begins in the middle of our white run, we must collapse
the white run from the left to that point.  If black ends in the
middle of our white run, we must collapse the white run from the right
to that point.
*/
       for (edge = swathstart; VALIDEDGE(edge); edge = edge->link) {
 
               if (!SAMESWATH(swathstart,edge))
                       break;
               if( XofY(edge, yblack) > XofY(left, ywhite)) {
                       if (ISLEFT(edge->flag)) {
                                x = XofY(edge, yblack);
                                if (XofY(right, ywhite) < x)
                                       x = XofY(right, ywhite);
                                writeXofY(left, ywhite, x);
                       }
                       else {
                                x = XofY(edge, yblack);
                                while (edge->link != NULL && SAMESWATH(edge, edge->link)
                                       && x >= XofY(edge->link, yblack) ) {
                                       edge = edge->link->link;
                                       x = XofY(edge, yblack);
                                }
                                if (x < XofY(right, ywhite))
                                       writeXofY(right, ywhite, x);
                                return;
                       }
               }
       }
       writeXofY(left, ywhite, XofY(right, ywhite));
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void ComputeHint ( struct hintsegment hP,
fractpel  currX,
fractpel  currY,
struct fractpoint hintP 
) [static]

Definition at line 126 of file hints.c.

{
  fractpel currRef=0, currWidth=0;
  int idealWidth;
  fractpel hintValue=0;
  char orientation;
 
/*
By construction, width is never zero.  Therefore we can use the
width value to determine if the hint has been rotated by a
multiple of 90 degrees.
*/
 
  if (hP->width.y == 0)
    {
    orientation = 'v';  /* vertical */
    IfTrace0((HintDebug > 0),"  vertical hint\n");
    }
  else if (hP->width.x == 0)
    {
    orientation = 'h';  /* horizontal */
    IfTrace0((HintDebug > 0),"  horizontal hint\n");
    }
  else
    {
    IfTrace0((HintDebug > 0),"  hint not vertical or horizontal\n");
    hintP->x = hintP->y = 0;
    return;
    }
 
  /* Compute currRef and currWidth with a unit of 1 pel */
  if (orientation == 'v')      /* vertical */
    {
    currRef = hP->ref.x + currX;
    currWidth = TYPE1_ABS(hP->width.x);
    }
  else if (orientation == 'h') /* horizontal */
    {
    currRef = hP->ref.y + currY;
    currWidth = TYPE1_ABS(hP->width.y);
    }
  else                             /* error */
    {
    abort("ComputeHint: invalid orientation", 4);
    }
 
  IfTrace4((HintDebug > 1),
    "  currX=%d, currY=%d, currRef=%d, currWidth=%d\n",
    currX, currY,
    currRef, currWidth);
 
  if ((hP->hinttype == 'b')      /* Bar or stem */
    || (hP->hinttype == 's'))    /* Serif */
    {
    idealWidth = NEARESTPEL(currWidth);
    if (idealWidth == 0) idealWidth = 1;
    if (ODD(idealWidth))         /* Is ideal width odd? */
      {
      /* center "ref" over pel */
      hintValue = FPFLOOR(currRef) + FPHALF - currRef;
      }
    else
      {
      /* align "ref" on pel boundary */
      hintValue = FPROUND(currRef) - currRef;
      }
    if (HintDebug > 2) {
          IfTrace1(TRUE,"  idealWidth=%d, ", idealWidth);
      }
    }
  else if (hP->hinttype == 'c')  /* Curve extrema */
    {
    /* align "ref" on pel boundary */
    hintValue = FPROUND(currRef) - currRef;
    }
  else                           /* error */
    {
    abort("ComputeHint: invalid hinttype", 5);
    }
 
  IfTrace1((HintDebug > 1),"  hintValue=%d", hintValue);
 
  if (orientation == 'v')      /* vertical */
    {
    hintP->x = hintValue;
    hintP->y = 0;
    }
  else if (orientation == 'h') /* horizontal */
    {
    hintP->x = 0;
    hintP->y = hintValue;
    }
  else                             /* error */
    {
    abort("ComputeHint: invalid orientation", 6);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void DumpSubPaths ( struct edgelist anchor) [static]

Definition at line 674 of file hints.c.

{
 
       register struct edgelist *edge,*e,*e2;
       pel y;
 
       for (edge = anchor; VALIDEDGE(edge); edge = edge->link) {
               if (ISPERMANENT(edge->flag))
                       continue;
               IfTrace0(TRUE, "BEGIN Subpath\n");
               for (e2 = edge; !ISPERMANENT(e2->flag);) {
                       if (ISDOWN(e2->flag)) {
                               IfTrace1(TRUE, ". Downgoing edge's top at %p\n", e2);
                               for (e = e2;; e = e->subpath) {
                                       IfTrace4(TRUE, ". . [%5d] %5d    @ %p[%x]\n",
                                                e->ymin, *e->xvalues, e, e->flag);
                                       for (y=e->ymin+1; y < e->ymax; y++)
                                               IfTrace2(TRUE, ". . [%5d] %5d     \"\n", y, e->xvalues[y-e->ymin]);
                                       e->flag |= ISPERMANENT(ON);
                                       if (ISBREAK(e, e->subpath))
                                               break;
                               }
                       }
                       else {
                               IfTrace1(TRUE, ". Upgoing edge's top at %p\n", e2);
                               for (e = e2; !ISBREAK(e, e->subpath); e = e->subpath) { ; }
                               for (;; e=before(e)) {
                                       IfTrace4(TRUE, ". . [%5d] %5d    @ %p[%x]\n",
                                                e->ymax-1, e->xvalues[e->ymax-1-e->ymin], e, e->flag);
                                       for (y=e->ymax-2; y >= e->ymin; y--)
                                               IfTrace2(TRUE, ". . [%5d] %5d      \"\n", y, e->xvalues[y-e->ymin]);
                                       e->flag |= ISPERMANENT(ON);
                                       if (e == e2)
                                               break;
                               }
                       }
                       do {
                               e2 = before(e2);
                       } while (!ISBREAK(before(e2), e2));
               }
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void FixSubPaths ( struct region R) [static]

Definition at line 502 of file hints.c.

{
  register struct edgelist *e;     /* fast loop variable                */
  register struct edgelist *edge;  /* current edge in region            */
  register struct edgelist *next;  /* next in subpath after 'edge'      */
  register struct edgelist *break1;  /* first break after 'next'        */
  register struct edgelist *break2=NULL; /* last break before 'edge'        */
  register struct edgelist *prev;    /* previous edge for fixing links  */
  int left = TRUE;
  
  for (edge = R->anchor; edge != NULL; edge = edge->link) {
        
    if (left)
      edge->flag |= ISLEFT(ON);
    left = !left;
    
    next = edge->subpath;
    
    if (!ISBREAK(edge, next))
      continue;
    if (edge->ymax < next->ymin)
      abort("disjoint subpath?", 13);
    /*
      'edge' now contains an edgelist at the bottom of an edge, and 'next'
      contains the next subsequent edgelist in the subpath, which must be at
      the top.  We refer to this a "break" in the subpath.
    */
    next->flag |= ISTOP(ON);
    edge->flag |= ISBOTTOM(ON);
    
    if (ISDOWN(edge->flag) != ISDOWN(next->flag))
      continue;
    /*
      We are now in the unusual case; both edges are going in the same
      direction so this must be a "false break" due to the way that the user
      created the path.  We'll have to fix it.
    */
    for (break1 = next; !ISBREAK(break1, break1->subpath); break1 = break1->subpath) { ; }
    
    for (e = break1->subpath; e != edge; e = e->subpath)
      if (ISBREAK(e, e->subpath))
       break2 = e;
    /*
      Now we've set up 'break1' and 'break2'.  I've found the following
      diagram invaluable.  'break1' is the first break after 'next'.  'break2'
      is the LAST break before 'edge'.
      &drawing.
      next
      +------+     +---->+------+
      +--->|    >-----+ |     |    >-----+
      |    |      |   | |     |      |   |
      | +-------------+ |  +-------------+
      | |  |break1|     |  |  |      |
      | +->|    >-------+  +->|    >-----+
      |    |      |           |      |   |
      |    |      |        +-------------+
      |    +------+        |  |      |
      | +----------------+ |  |      |
      | |  +------+      | +->|    >-----+
      | +->|    >-----+  |    |      |   |
      |    |      |   |  | +-------------+
      | +-------------+  | |  |      |
      | |  |edge  |      | |  |break2|
      | +->|    >-----+  | +->|    >-----+
      |    |      |   |  |    |      |   |
      |    |      |   |  |    |      |   |
      |    |      |   |  |    |      |   |
      |    +------+   |  |    +------+   |
      |               |  |               |
      +---------------+  +---------------+
      
      &edrawing.
      We want to fix this situation by having 'edge' point to where 'break1'
      now points, and having 'break1' point to where 'break2' now points.
      Finally, 'break2' should point to 'next'.  Also, we observe that
      'break1' can't be a bottom, and is also not a top unless it is the same
      as 'next':
    */
    edge->subpath = break1->subpath;
    
    break1->subpath = break2->subpath;
    if (ISBREAK(break1, break1->subpath))
      abort("unable to fix subpath break?", 14);
    
    break2->subpath = next;
    
    break1->flag &= ~ISBOTTOM(ON);
    if (break1 != next)
      break1->flag &= ~ISTOP(ON);
  }
  
  /*
    This region might contain "ambiguous" edges; edges exactly equal to
    edge->link.  Due to the random dynamics of where they get sorted into
    the list, they can yield false crossings, where the edges appear
    to cross.  This confuses our continuity logic no end.  Since we can
    swap them without changing the region, we do.
  */
  for (edge = R->anchor, prev = NULL; VALIDEDGE(edge); prev = edge, edge = prev->link) {
    
    if (! ISAMBIGUOUS(edge->flag)) {
      continue;
    }
    
    next = edge->subpath;
    
    while (ISAMBIGUOUS(next->flag) && next != edge) {
      next = next->subpath;
    }
    
    /*
      We've finally found a non-ambiguous edge; we make sure it is left/right
      compatible with 'edge':
    */
    if ( (ISLEFT(edge->flag) == ISLEFT(next->flag) && ISDOWN(edge->flag) == ISDOWN(next->flag) )
        || (ISLEFT(edge->flag) != ISLEFT(next->flag) && ISDOWN(edge->flag) != ISDOWN(next->flag) ) ) {
      continue;
    }
    
    /*
      Incompatible, we will swap 'edge' and the following edge in the list.
      You may think that there must be a next edge in this swath.  So did I.
      No!  If there is a totally ambiguous inner loop, for example, we could
      get all the way to the outside without resolving ambiguity.
    */
    next = edge->link;  /* note new meaning of 'next' */
    if (next == NULL || edge->ymin != next->ymin) {
      continue;
    }
    
    /* 
       printf("      Swap:                \n");
       printf("            Edge=0x%x, ymin=%d, ymax=%d, xmin=%d, xmax=%d, fpx1=%ld, fpx2=%ld\n",
       edge, edge->ymin, edge->ymax, edge->xmin, edge->xmax, edge->fpx1, edge->fpx2);
       printf("            Link=0x%x, ymin=%d, ymax=%d, xmin=%d, xmax=%d, fpx1=%ld, fpx2=%ld\n",
       next, next->ymin, next->ymax, next->xmin, next->xmax, next->fpx1, next->fpx2);
       printf("            Edge=0x%x (amb=%d), x[ymin]=%d, x[ymax]=%d, px1=%ld, px2=%ld\n",
       edge, ISAMBIGUOUS(edge->flag), edge->xvalues[0], edge->xvalues[edge->ymax - edge->ymin],
       edge->fpx1>>FRACTBITS, edge->fpx2>>FRACTBITS);
       printf("            Link=0x%x (amb=%d), x[ymin]=%d, x[ymax]=%d, px1=%ld, px2=%ld\n",
       next, ISAMBIGUOUS(next->flag), next->xvalues[0], next->xvalues[next->ymax - next->ymin],
       next->fpx1>>FRACTBITS, next->fpx2>>FRACTBITS);
    */

    /* Check ambiguity also for link edge (RMz) */
    if ( !ISAMBIGUOUS(next->flag) ) {
      continue;
    }
    
    
    if (prev == NULL)
      R->anchor = next;
    else
      prev->link = next;
    edge->link = next->link;
    next->link = edge;
    edge->flag ^= ISLEFT(ON);
    edge->flag &= ~ISAMBIGUOUS(ON);
    next->flag ^= ISLEFT(ON);
    next->flag &= ~ISAMBIGUOUS(ON);
    edge = next;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ImpliedHorizontalLine ( struct edgelist e1,
struct edgelist e2,
int  y 
) [static]

Definition at line 429 of file hints.c.

{
       register struct edgelist *e3,*e4;
 
       if (ISDOWN(e1->flag) == ISDOWN(e2->flag))
               return(NONE);  /* can't be consecutive unless different directions */
/*
Now we check for consecutiveness:  Can we get from 'e1' to 'e2' with
only one intervening break?  Can we get from 'e2' to 'e1' with only one
intervening break?  'e3' will be as far as we can get after 'e1'; 'e4'
will be has far as we can get after 'e2':
*/
       for (e3 = e1; !ISBREAK(e3, e3->subpath); e3 = e3->subpath) { ; }
       for (e3 = e3->subpath; e3 != e2; e3 = e3->subpath)
               if (ISBREAK(e3, e3->subpath))
                       break;
 
       for (e4 = e2; !ISBREAK(e4, e4->subpath); e4 = e4->subpath) { ; }
       for (e4 = e4->subpath; e4 != e1; e4 = e4->subpath)
               if (ISBREAK(e4, e4->subpath))
                       break;
/*
If the edges are mutually consecutive, we must have horizontal lines
both top and bottom:
*/
       if (e3 == e2 && e4 == e1)
               return(TRUE);
/*
If the edges are not consecutive either way, no horizontal lines are
possible:
*/
       if (e3 != e2 && e4 != e1)
               return(NONE);
/*
Now let's swap 'e1' and 'e2' if necessary to enforce the rule that 'e2'
follows 'e1'.  Remember that subpath chains go in the opposite direction
from the way the subpaths were built; this led to the simplest way
do build them.
*/
       if (e4 != e1) {
               e2 = e1;
               e1 = e3;  /* remember e3 == e2, this just swaps 'e1' and 'e2' */
       }
/*
Now we have everything to return the answer:
*/
       if (ISTOP(e1->flag) && y == e1->ymin)
               return(ISDOWN(e2->flag));
       else if (ISBOTTOM(e1->flag) && y == e1->ymax)
               return(!ISDOWN(e2->flag));
       else
               abort("ImpliedHorizontalLine:  why ask?", 12);
       /*NOTREACHED*/
       /* To make ANSI-C-compiler happy */
       return(0);
       
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 87 of file hints.c.

{
  int i;
 
  for (i = 0; i < MAXLABEL; i++)
    {
    oldHint[i].inuse    = FALSE;
    oldHint[i].computed = FALSE;
    }
}
void ProcessHint ( struct hintsegment hP,
fractpel  currX,
fractpel  currY,
struct fractpoint hintP 
)

Definition at line 231 of file hints.c.

{
  struct fractpoint thisHint;
 
  IfTrace4((HintDebug > 1),"  ref=(%d,%d), width=(%d,%d)",
      hP->ref.x, hP->ref.y,
      hP->width.x, hP->width.y);
  IfTrace4((HintDebug > 1),", %c %c %c %c",
      hP->orientation, hP->hinttype,
      hP->adjusttype, hP->direction);
  IfTrace1((HintDebug > 1),", label=%d\n", hP->label);
 
  if ((hP->adjusttype == 'm')      /* Move */
    || (hP->adjusttype == 'a'))    /* Adjust */
    {
    /* Look up hint in oldHint table */
    if ((hP->label >= 0) && (hP->label < MAXLABEL))
      {
      if (oldHint[hP->label].computed)
        /* Use old hint value if already computed */
        {
        thisHint.x = oldHint[hP->label].hint.x;
        thisHint.y = oldHint[hP->label].hint.y;
        oldHint[hP->label].inuse    = TRUE;
        }
      else
        /* Compute new value for hint and store it for future use */
        {
        ComputeHint(hP, currX, currY, &thisHint);
 
        oldHint[hP->label].hint.x = thisHint.x;
        oldHint[hP->label].hint.y = thisHint.y;
        oldHint[hP->label].inuse    = TRUE;
        oldHint[hP->label].computed = TRUE;
        }
      }
    else                             /* error */
      {
      abort("ProcessHint: invalid label", 7);
      }
    }
  else if (hP->adjusttype == 'r')  /* Reverse */
    {
    /* Use the inverse of the existing hint value to reverse hint */
    if ((hP->label >= 0) && (hP->label < MAXLABEL))
      {
      if (oldHint[hP->label].inuse)
        {
        thisHint.x = -oldHint[hP->label].hint.x;
        thisHint.y = -oldHint[hP->label].hint.y;
        oldHint[hP->label].inuse = FALSE;
        }
      else                           /* error */
        {
        abort("ProcessHint: label is not in use", 8);
        }
      }
    else                           /* error */
      {
      abort("ProcessHint: invalid label", 9);
      }
 
    }
  else                           /* error */
    {
    abort("ProcessHint: invalid adjusttype", 10);
    }
  IfTrace3((HintDebug > 1),"  label=%d, thisHint=(%d,%d)\n",
    hP->label, thisHint.x, thisHint.y);
 
  hintP->x += thisHint.x;
  hintP->y += thisHint.y;
 
  IfTrace2((HintDebug > 1),"  hint=(%d,%d)\n",
    hintP->x, hintP->y);
}

Here is the call graph for this function:

static pel SearchXofY ( struct edgelist edge,
pel  y 
) [static]

Definition at line 368 of file hints.c.

{
  register struct edgelist *e;  /* loop variable                        */
  
  if (y < edge->ymin) {
    if (ISTOP(edge->flag)) {
      return(MINPEL);
    }
    
    for (e = edge->subpath; e->subpath != edge; e = e->subpath) { ; }
    if (e->ymax == edge->ymin) {
      return(XofY(e, y));
    }
  }
  else if (y >= edge->ymax) {
    if (ISBOTTOM(edge->flag)) {
      return(MINPEL);
    }
    e = edge->subpath;
    if (e->ymin == edge->ymax) {
      return(XofY(e, y));
    }
  }
  else {
    return(XofY(edge, y));
  }
  
  
  abort("bad subpath chain", 11);
  /*NOTREACHED*/
  /* To make ANSI-C-compiler happy: */
  return(y);
  
}

Here is the call graph for this function:

static void writeXofY ( struct edgelist e,
int  y,
int  x 
) [static]

Definition at line 751 of file hints.c.

{
  if (e->xmin > x)  e->xmin = x;
  if (e->xmax < x)  e->xmax = x;
  e->xvalues[y - e->ymin] = x;
}

Here is the caller graph for this function:


Variable Documentation

struct { ... } oldHint[MAXLABEL] [static]