Logo Search packages:      
Sourcecode: yudit version File versions

void SFontTTF::drawGlyph ( SCanvas canvas,
const SS_Matrix2D matrix,
SS_GlyphIndex  glyphno 
) [protected]

Draw a single glyph. canvas is the canvas to draw to

Parameters:
pen is the pen to draw with
m is the transformation matrix.
glyphindex is the local glyph index
Returns:
nothing

Definition at line 2662 of file SFontTTF.cpp.

References SBinVector< Type >::append(), SCanvas::closepath(), SS_Matrix2D::t0, SS_Matrix2D::t1, SS_Matrix2D::x0, SS_Matrix2D::x1, SS_Matrix2D::y0, and SS_Matrix2D::y1.

Referenced by draw().

{
  if (!isOK()) return ;
  if (glyphno == SD_G_INDIC_ZWJ) return;
  if (glyphno == SD_G_INDIC_ZWNJ) return;

  SD_BYTE* gstart = (SD_BYTE *) tables[SS_TB_GLYF];

  TTF_GLYF* gtable;
  int len =0;
  if (longOffsets)
  {
     SD_ULONG* lloca = (SD_ULONG *) tables[SS_TB_LOCA];
     unsigned int offs1 = ntohl (lloca[glyphno]);
     unsigned int offs2 = ntohl (lloca[glyphno+1]);
     gtable = (TTF_GLYF *) ((char*)gstart + offs1);
     len = offs2-offs1;
  }
  else
  {
     SD_USHORT* sloca = (SD_USHORT *) tables[SS_TB_LOCA];
     gtable = (TTF_GLYF *) (gstart + (ntohs (sloca[glyphno]) << 1));
     len = (ntohs (sloca[glyphno+1]) - ntohs (sloca[glyphno])) << 1;
  }
  if (len <= 0)
  {
    if (!broken && len < 0)
    {
      fprintf (stderr, "SFontTTF-2: non-existent glyph %u in %*.*s %d\n",
          (unsigned int) glyphno,
          SSARGS (name), (int) len) ;
      broken = true;
    }
    return;
  }
  TTF_GLYF* kludge = 0;
  if ((((unsigned long) gtable) & 1) != 0)
  {
    if (!broken)
    {
      fprintf  (stderr, "SFontTTF: fixing unaligned %*.*s.\n", SSARGS(name));
      broken = true;
    }
    kludge = new TTF_GLYF[len]; 
    CHECK_NEW (kludge);
    memcpy (kludge, gtable, len * sizeof (TTF_GLYF));
    gtable = kludge;
  }

  int ncontours = (int) ((short)ntohs (gtable->numberOfContours));
  if (ncontours <= 0)
  {
    SD_BYTE *ptr = ((SD_BYTE *) gtable + sizeof(TTF_GLYF));
    SD_SHORT *sptr = (SD_SHORT *) ptr;
    SD_USHORT flagbyte;
    do
    {
      SS_Matrix2D m;
      flagbyte = ntohs(*sptr); sptr ++;
      SS_GlyphIndex glyphindex = ntohs(*sptr); sptr ++;

      if (flagbyte & ARG_1_AND_2_ARE_WORDS)
      {
         /* we need to make it short as it can be negative */
         m.t0 = (double) ((SD_SHORT)ntohs(*sptr)); sptr++;
         m.t1 = (double) ((SD_SHORT)ntohs(*sptr)); sptr++;
      }
      else
      {
         char* bptr = (char *)sptr;
         m.t0 = (signed char)bptr[0];
         m.t1 = (signed char)bptr[1];
         sptr ++;
      }
      if (flagbyte & WE_HAVE_A_SCALE)
      {
         m.x0 = m.y1 = f2dot14(*sptr);
         sptr ++;
      }
      else if (flagbyte & WE_HAVE_AN_X_AND_Y_SCALE)
      {
        m.x0 = f2dot14(*sptr); sptr ++;
        m.y1 = f2dot14(*sptr); sptr ++;
      }
      else if (flagbyte & WE_HAVE_A_TWO_BY_TWO)
      {
        m.x0 = f2dot14(*sptr); sptr ++;
        m.y0 = f2dot14(*sptr); sptr ++;
        m.x1 = f2dot14(*sptr); sptr ++;
        m.y1 = f2dot14(*sptr); sptr ++;
      }
      SS_Matrix2D mm = matrix * m;
      /* recursively call itself */
      drawGlyph (canvas, mm, glyphindex);
    } while (flagbyte & MORE_COMPONENTS);
    if (kludge) delete kludge;
    return;
  }

  SD_USHORT* contour_end_pt = (SD_USHORT *) ((char *)gtable + sizeof(TTF_GLYF));

  int last_point = (int) ntohs (contour_end_pt[ncontours-1]);

  int n_inst = (int) ntohs (contour_end_pt[ncontours]);

  SD_BYTE* ptr = ((SD_BYTE *)contour_end_pt) + (ncontours << 1) + n_inst + 2;

  int j = 0; int k = 0;

  SBinVector<SD_BYTE> flags;
  while (k <= last_point)
  {
    flags.append (ptr[j]);
    if (ptr[j] & REPEAT)
    {
       for (int k1=0; k1 < ptr[j+1]; k1++)
       {
            k++;
            flags.append (ptr[j]);
       }
       j++;
    }
    j++; k++;
  }
  
  SBinVector<SD_SHORT> xrel;
  SBinVector<SD_SHORT> xcoord;

  for (k=0; k <= last_point; k++)
  {
    /* Process xrel */
    if (flags[k] & XSD_SHORT)
    {
      if (flags[k] & XSAME)
      {
        xrel.append (ptr[j]);
      }
      else
      {
        xrel.append (-ptr[j]);
      }
      j++;
    }
    else if (flags[k] & XSAME)
    {
      xrel.append (0);
    }
    else
    {
      xrel.append (ptr[j] * 256 + ptr[j+1]);
      j += 2;
    }
    /* Process x coordinate */
    if (k==0)
    {
      xcoord.append (xrel[k]);
    }
    else
    {
      xcoord.append (xrel[k] + xcoord[k-1]);
    }
  }

  SBinVector<SD_SHORT> yrel;
  SBinVector<SD_SHORT> ycoord;

  /* one more run fore yrel and ycoord */
  for (k=0; k <= last_point; k++)
  {
    if (flags[k] & YSD_SHORT)
    {
      if (flags[k] & YSAME)
      {
        yrel.append (ptr[j]);
      }
      else
      {
         yrel.append (- ptr[j]);
      }
      j++;
    }
    else if (flags[k] & YSAME)
    {
      yrel.append (0);
    }
    else
    {
      yrel.append (ptr[j] * 256 + ptr[j+1]);
      j += 2;
    }
    if (k==0)
    {
       ycoord.append (yrel[k]);
    }
    else
    {
       ycoord.append (yrel[k] + ycoord[k-1]);
    }
  }

  bool first = true;

  j = 0;
  int i = 0;
  int contour_start = 0;
  while (i <= ntohs(contour_end_pt[ncontours-1]))
  {
    int contour_end = ntohs(contour_end_pt[j]);

    if (first)
    {
      moveto (canvas, matrix, xcoord[i], ycoord[i]);
      contour_start = i;
      first = false;
    }
    else if (flags[i] & ONOROFF)
    {
      lineto (canvas, matrix, xcoord[i], ycoord[i]);
    }
    else /* curvy */
    {
      int cs = i-1;
      int ce = 0;
      bool finished = false;
      int nguide = 0;
      while (!finished)
      {
        if (i == contour_end+1)
        {
          ce = contour_start;
          finished = true;
        }
        else if (flags[i] & ONOROFF)
        {
          ce = i;
          finished = true;
        }
        else
        {
           i++;
           nguide++;
        }
      }

      switch (nguide)
      {
      case 0:
        lineto (canvas, matrix, xcoord[ce], ycoord[ce]);
        break;

      case 1:
        cureveto (canvas, matrix, 
           (xcoord[cs]+2*xcoord[cs+1])/3, (ycoord[cs]+2*ycoord[cs+1])/3,
           (2*xcoord[cs+1]+xcoord[ce])/3, (2*ycoord[cs+1]+ycoord[ce])/3,
            xcoord[ce], ycoord[ce]);
        break;

      case 2: 
        cureveto (canvas, matrix, 
            (-xcoord[cs]+4*xcoord[cs+1])/3, (-ycoord[cs]+4*ycoord[cs+1])/3,
            (4*xcoord[cs+2]-xcoord[ce])/3, (4*ycoord[cs+2]-ycoord[ce])/3,
            xcoord[ce], ycoord[ce]);
        break;

      case 3: 
        cureveto (canvas, matrix, 
            (xcoord[cs]+2*xcoord[cs+1])/3, (ycoord[cs]+2*ycoord[cs+1])/3,
            (5*xcoord[cs+1]+xcoord[cs+2])/6, (5*ycoord[cs+1]+ycoord[cs+2])/6,
            (xcoord[cs+1]+xcoord[cs+2])/2, (ycoord[cs+1]+ycoord[cs+2])/2);
        cureveto (canvas, matrix,
            (xcoord[cs+1]+5*xcoord[cs+2])/6, (ycoord[cs+1]+5*ycoord[cs+2])/6,
            (5*xcoord[cs+2]+xcoord[cs+3])/6, (5*ycoord[cs+2]+ycoord[cs+3])/6,
            (xcoord[cs+3]+xcoord[cs+2])/2, (ycoord[cs+3]+ycoord[cs+2])/2);
        cureveto (canvas, matrix,
            (xcoord[cs+2]+5*xcoord[cs+3])/6, (ycoord[cs+2]+5*ycoord[cs+3])/6,
            (2*xcoord[cs+3]+xcoord[ce])/3, (2*ycoord[cs+3]+ycoord[ce])/3,
            xcoord[ce], ycoord[ce]);
        break;

      default:
        int k1 = cs + nguide;
        cureveto (canvas, matrix, 
            (xcoord[cs]+2*xcoord[cs+1])/3, (ycoord[cs]+2*ycoord[cs+1])/3,
            (5*xcoord[cs+1]+xcoord[cs+2])/6, (5*ycoord[cs+1]+ycoord[cs+2])/6,
            (xcoord[cs+1]+xcoord[cs+2])/2, (ycoord[cs+1]+ycoord[cs+2])/2);
        for (k = cs+2; k <= k1-1; k++)
        {
          cureveto (canvas, matrix, 
            (xcoord[k-1]+5*xcoord[k])/6, (ycoord[k-1]+5*ycoord[k])/6,
            (5*xcoord[k]+xcoord[k+1])/6, (5*ycoord[k]+ycoord[k+1])/6,
            (xcoord[k]+xcoord[k+1])/2, (ycoord[k]+ycoord[k+1])/2);
        }
        cureveto (canvas, matrix, 
            (xcoord[k1-1]+5*xcoord[k1])/6, (ycoord[k1-1]+5*ycoord[k1])/6,
            (2*xcoord[k1]+xcoord[ce])/3, (2*ycoord[k1]+ycoord[ce])/3,
            xcoord[ce], ycoord[ce]);
        break;
      } /* end switch (nguide) */
    }
    if (i >= contour_end)
    {
      first = true;
      i = contour_end + 1;
      canvas->closepath ();
      j++;
    }
    else
    {
      i++;
    }
  }
  if (kludge!=0) delete kludge;
  return;
}


Generated by  Doxygen 1.6.0   Back to index