示例#1
0
/* Get shape of text input to GdText, given a function Width which can
   compute the width of a simple text string (no imbedded \n).  Returns
   largest value of Width for any line, and a line count.  */
int GtTextShape(const char *text, const GpTextAttribs *t,
                WidthFunction Width, GpReal *widest)
{
    int path= t->orient;
    GpReal wdest, thisWid;
    int nLines, nChars;

    /* Count lines in this text, find widest line */
    nLines= 0;
    wdest= 0.0;
    while ((text= GtNextLine(text, &nChars, path))) {
        nLines++;
        if (Width) thisWid= Width(text, nChars, t);
        else thisWid= (GpReal)nChars;
        if (thisWid>wdest) wdest= thisWid;
        text+= nChars;
    }

    *widest= wdest;
    return nLines;
}
示例#2
0
文件: ps.c 项目: MattWherry/yorick
static int DrwText(Engine *engine, GpReal x0, GpReal y0, const char *text)
{
  PSEngine *psEngine= (PSEngine *)engine;
  int ix, iy, nlines;
  GpReal width, height, lineHeight;
  GpXYMap *map= &engine->map;
  GpBox *wind= &engine->transform.window;
  GpReal xmin, xmax, ymin, ymax;
  int xll, yll, xur, yur, alignH, alignV;
  int count, nchars, firstPass;
  char *now, c;
  const char *t;
  int state= 0;

  /* zero size text can confuse postscript interpreters */
  if ((int)(gistA.t.height*NDC_TO_PS+0.5) <= 0) return 0;

  if (CheckClip(psEngine) || SetupText(psEngine)) return 1;
  alignH= psEngine->curAlignH;
  alignV= psEngine->curAlignV;
  /* Compute text location in PostScript coordinates.  */
  x0= map->x.scale*x0 + map->x.offset;
  y0= map->y.scale*y0 + map->y.offset;

  /* handle multi-line strings */
  nlines= GtTextShape(text, &gistA.t, (WidthFunction)0, &width);
  lineHeight= gistA.t.height * NDC_TO_PS;
  width*= 0.6*lineHeight;
  height= lineHeight*(GpReal)nlines;

  /* Reject if and only if the specified point is off of the current
     page by more than the approximate size of the text.  Note that
     the entire block of text is either accepted or rejected --
     PostScript does the clipping.  */
  if (wind->xmax>wind->xmin) { xmin= wind->xmin; xmax= wind->xmax; }
  else { xmin= wind->xmax; xmax= wind->xmin; }
  if (wind->ymax>wind->ymin) { ymin= wind->ymin; ymax= wind->ymax; }
  else { ymin= wind->ymax; ymax= wind->ymin; }
  if (gistA.t.orient==TX_RIGHT || gistA.t.orient==TX_LEFT) {
    if (x0<xmin-width || x0>xmax+width ||
        y0<ymin-height || y0>ymax+height) return 0;
  } else {
    if (x0<xmin-height || x0>xmax+height ||
        y0<ymin-width || y0>ymax+width) return 0;
  }

  /* Adjust y0 (or x0) to represent topmost line */
  if (nlines > 1) {
    if (gistA.t.orient==TX_RIGHT) {
      if (alignV==TV_BASE || alignV==TV_BOTTOM) y0+= height-lineHeight;
      if (alignV==TV_HALF) y0+= 0.5*(height-lineHeight);
    } else if (gistA.t.orient==TX_LEFT) {
      if (alignV==TV_BASE || alignV==TV_BOTTOM) y0-= height-lineHeight;
      if (alignV==TV_HALF) y0-= 0.5*(height-lineHeight);
    } else if (gistA.t.orient==TX_UP) {
      if (alignV==TV_BASE || alignV==TV_BOTTOM) x0-= height-lineHeight;
      if (alignV==TV_HALF) x0-= 0.5*(height-lineHeight);
    } else {
      if (alignV==TV_BASE || alignV==TV_BOTTOM) x0+= height-lineHeight;
      if (alignV==TV_HALF) x0+= 0.5*(height-lineHeight);
    }
  }

  ix= (int)x0;
  iy= (int)y0;

  /* Guess at the bounding box for the text */
  if (!psEngine->curClip) {
    GpReal dx=0.0, dy=0.0;
    if (alignH==TH_CENTER) dx= 0.5*width;
    else if (alignH==TH_RIGHT) dx= width;
    if (alignV==TV_TOP || alignV==TV_CAP) dy= height;
    else if (alignV==TV_HALF) dy= height-0.4*lineHeight;
    else if (alignV==TV_BASE) dy= height-0.8*lineHeight;
    else if (alignV==TV_BOTTOM) dy= height-lineHeight;
    if (gistA.t.orient==TX_RIGHT) {
      x0-= dx;
      y0-= dy;
    } else if (gistA.t.orient==TX_LEFT) {
      x0+= dx;
      y0+= dy;
    } else if (gistA.t.orient==TX_UP) {
      x0-= dy;
      y0+= dx;
    } else {
      x0+= dy;
      y0-= dx;
    }
    if (x0>xmin) xmin= x0;
    if (x0+width<xmax) xmax= x0+width;
    if (y0>ymin) ymin= y0;
    if (y0+height<ymax) ymax= y0+height;
    xll= (int)xmin;
    xur= (int)xmax;
    yll= (int)ymin;
    yur= (int)ymax;
    if (xll<psEngine->pageBB.xll) psEngine->pageBB.xll= xll;
    if (xur>psEngine->pageBB.xur) psEngine->pageBB.xur= xur;
    if (yll<psEngine->pageBB.yll) psEngine->pageBB.yll= yll;
    if (yur>psEngine->pageBB.yur) psEngine->pageBB.yur= yur;
  }

  if (nlines>1 || gistA.t.orient!=TX_RIGHT) {
    if (Append(psEngine, "[")) return 1;
  }

  nchars= psEngine->nchars;
  now= psEngine->line+nchars;
  firstPass= 1;
  while ((t= GtNextLine(text, &count, gistA.t.orient)) || firstPass) {
    text= t;
    firstPass= 0;
    state= 0;

    if (nchars > 70) {
      psEngine->nchars= nchars;
      if (PutLine(psEngine)) return 1;
      nchars= 0;
      now= psEngine->line;
    }
    *now++= ' ';
    *now++= '(';
    nchars+= 2;

    while (count--) {
      if (nchars>72 && break_line_now(psEngine, &now, &nchars)) return 1;

      c= *text;
      if (c>=32 && c<127) {
        if (gtDoEscapes) {
          if (c=='!' && count) {
            c= text[1];  /* peek at next char */
            if (c=='!' || c=='^' || c=='_') {
              count--;
              text++;
              goto normal;
            }
            if (nchars>68 &&
                break_line_now(psEngine, &now, &nchars)) return 1;
            strcpy(now, "\\024");  /* DC4 is ps.ps escape char */
            now+= 4;
            nchars+= 4;
            psEngine->fonts|= (1<<T_SYMBOL);  /* symbol font used */
            if (c==']') {
              *now++= '^';         /* !] means ^ (perp) in symbol font */
              nchars++;
              text+= 2;
              count--;
              continue;
            }
            goto escape;
          } else if (c=='^') {
            if (state!=0) {
              /* terminate current super or subscript escape */
              strcpy(now, "\\021");  /* DC1 is ps.ps escape char */
              now+= 4;
              nchars+= 4;
            }
            if (state!=1) {
              /* intialize superscript escape */
              if (nchars>64 &&
                  break_line_now(psEngine, &now, &nchars)) return 1;
              strcpy(now, "\\021\\022");  /* DC1DC2 is ps.ps escape seq */
              now+= 8;
              nchars+= 8;
              state= 1;
            } else {
              state= 0;
            }
            goto escape;
          } else if (c=='_') {
            if (state!=0) {
              /* terminate current super or subscript escape */
              if (nchars>68 &&
                  break_line_now(psEngine, &now, &nchars)) return 1;
              strcpy(now, "\\021");  /* DC1 is ps.ps escape char */
              now+= 4;
              nchars+= 4;
            }
            if (state!=2) {
              /* intialize subscript escape */
              if (nchars>64 &&
                  break_line_now(psEngine, &now, &nchars)) return 1;
              strcpy(now, "\\021\\023");  /* DC1DC3 is ps.ps escape seq */
              now+= 8;
              nchars+= 8;
              state= 2;
            } else {
              state= 0;
            }
            goto escape;
          }
        }
        /* ordinary printing character */
        if (c=='(' || c==')' || c=='\\') {
          *now++= '\\';
          nchars++;
        }
      normal:
        *now++= c;
        nchars++;
      } else {
        /* non-printing characters rendered as \ooo */
        if (c=='\t') {
          *now++= '\\';
          *now++= 't';
          nchars+= 2;
        } else if (c<'\021' || c>'\024') {
          /* DC1 through DC4 have special meaning in ps.ps, skip them */
          sprintf(now, "\\%03o", (int)((unsigned char)c));
          now+= 4;
          nchars+= 4;
        }
      }
    escape:
      text++;
    }
    if (state!=0) {
      /* terminate current super or subscript escape */
      strcpy(now, "\\021");  /* DC1 is ps.ps escape char */
      now+= 4;
      nchars+= 4;
    }

    *now++= ')';
    nchars++;
    *now= '\0';
  }
  psEngine->nchars= nchars;

  if (gistA.t.orient==TX_RIGHT) {
    sprintf(line, nlines>1? "] %d %d TA" : "%d %d T", ix, iy);
  } else {
    int angle;
    if (gistA.t.orient==TX_LEFT) angle= 180;
    else if (gistA.t.orient==TX_UP) angle= 90;
    else angle= 270;
    sprintf(line, "] %d %d %d TR", angle, ix, iy);
  }
  if (Append(psEngine, line)) return 1;

  return 0;
}
示例#3
0
int
GxJustifyNext(const char **text, int *ix, int *iy)
{
  const char *txt= *text+nChunk;
  int xadj= 0, yadj= 0;
  char c;

  nChars-= nChunk;
  if (!nChars) {
    /* last chunk was the last one on a line */
    txt= GtNextLine(txt, &nChars, 0);
    if (!txt) return -1;

    *text= txt;

    /* scan for end of first chunk */
    if (gtDoEscapes) {
      for (nChunk=0 ; nChunk<nChars ; nChunk++) {
        c= txt[nChunk];
        if ((nChunk+1<nChars && c=='!') || c=='^' || c=='_') break;
      }
    } else {
      nChunk= nChars;
    }

    /* compute width of this chunk if necessary, compute width
       of whole line if necessary for justification */
    if (alignH!=TH_LEFT || gistA.t.orient!=TX_RIGHT) {
      /* need to compute width of entire line */
      int width= prevWidth;
      firstTextLine= 1;
      prevWidth= (int)TextWidth(txt, nChars, &gistA.t);
      if (alignH==TH_CENTER) xadj= (width-prevWidth)/2;
      else if (alignH==TH_RIGHT) xadj= width-prevWidth;
      /* TextWidth sets chunkWidth */
    } else if (nChunk<nChars) {
      /* just need width of this chunk */
      if (nChunk) chunkWidth = p_txwidth(current_scr, txt, nChunk,
                                         gistA.t.font, current_fsize);
      else chunkWidth= 0;  /* unused */
    }

    /* reset state, adjusting (possibly rotated) x and y as well */
    xadj-= x_chunks;
    yadj= lineHeight;
    if (current_state&1) yadj+= dy_super;
    else if (current_state&2) yadj-= dy_sub;
    if (nChunk && (current_state&4))
      p_font(current_win, gistA.t.font, current_fsize, gistA.t.orient);
    current_state= 0;

  } else {
    /* previous chunk ended with an escape character, or was single
       escaped symbol character -- can't get here unles gtDoEscapes */
    char c1= '\0';
    xadj= chunkWidth;      /* width of previous chunk */
    x_chunks+= chunkWidth; /* accumulate all chunks except last */
    yadj= 0;
    if (!(current_state&4)) {
      c1= *txt++;
      nChars--;
    }
    *text= txt;

    if (c1=='!') {
      /* this chunk begins with escaped character */
      nChunk= 1;
      c= txt[0];
      if (c=='!' || c=='^' || c=='_') {
        /* chunk is just ordinary text */
        for ( ; nChunk<nChars ; nChunk++) {
          c= txt[nChunk];
          if ((nChunk+1<nChars && c=='!') || c=='^' || c=='_') break;
        }
        p_font(current_win, gistA.t.font, current_fsize, gistA.t.orient);
        current_state&= 3;
      } else {
        /* chunk is single symbol char */
        p_font(current_win, current_fsym, current_fsize, gistA.t.orient);
        current_state|= 4;
      }

    } else {
      for (nChunk=0 ; nChunk<nChars ; nChunk++) {
        c= txt[nChunk];
        if ((nChunk+1<nChars && c=='!') || c=='^' || c=='_') break;
      }
      if (nChunk)
        p_font(current_win, gistA.t.font, current_fsize, gistA.t.orient);
      if (c1=='^') {
        if (current_state&1) {
          yadj+= dy_super;  /* return from super to normal */
          current_state= 0;
        } else {
          if (current_state&2) yadj-= dy_sub;
          yadj-= dy_super;  /* move to superscript */
          current_state= 1;
        }
      } else if (c1=='_') {
        if (current_state&2) {
          yadj-= dy_sub;  /* return from sub to normal */
          current_state= 0;
        } else {
          if (current_state&1) yadj+= dy_super;
          yadj+= dy_sub;  /* move to subscript */
          current_state= 2;
        }
      } else {
        /* just finished a symbol char */
        current_state&= 3;
      }
    }

    if (nChunk &&
        (nChunk<nChars || alignH!=TH_LEFT || gistA.t.orient!=TX_RIGHT)) {
      char caret= '^';
      if (nChunk==1 && (current_state&4) && txt[0]==']') txt= &caret;
      chunkWidth = p_txwidth(current_scr, txt, nChunk,
                             (current_state&4)? current_fsym : gistA.t.font,
                             current_fsize);
    } else {
      chunkWidth= 0;  /* unused */
    }
  }

  if (gistA.t.orient==TX_RIGHT) {
    *iy+= yadj;
    *ix+= xadj;
  } else if (gistA.t.orient==TX_LEFT) {
    *iy-= yadj;
    *ix-= xadj;
  } else if (gistA.t.orient==TX_UP) {
    *ix+= yadj;
    *iy-= xadj;
  } else {
    *ix-= yadj;
    *iy+= xadj;
  }

  return nChunk;
}