Example #1
0
static uint32_t pk_packed_num(unsigned char** pos)
{
  register int    i;
  uint32_t        j;

  i = (int)getnyb(pos);
  if (i == 0) {
    do {
      j = (uint32_t)getnyb(pos);
      i++;
    } while (j == 0);
    while (i > 0) {
      j = j * 16 + (uint32_t)getnyb(pos);
      i--;
    };
    return (j - 15 + (13 - dyn_f) * 16 + dyn_f);
  } else if (i <= (int)dyn_f) {
    return ((uint32_t)i);
  } else if (i < 14) {
    return ((i-(uint32_t)dyn_f - 1) * 16 + (uint32_t)getnyb(pos)
	    + dyn_f + 1);
  } else {
    if (i == 14) {
      repeatcount = (int)pk_packed_num(pos);
    } else {
      repeatcount = 1;
    }
    return (pk_packed_num(pos));    /* tail end recursion !! */
  }
}
Example #2
0
static int
pk_decode_packed (pdf_obj *stream, long wd, long ht,
                  int dyn_f, int run_color, unsigned char *dp, long pl)
{
  unsigned char  *rowptr;
  long            rowbytes;
  long            i, np = 0;
  long            run_count = 0, repeat_count = 0;

  rowbytes = (wd + 7) / 8;
  rowptr   = NEW(rowbytes, unsigned char);
  /* repeat count is applied to the *current* row.
   * "run" can span across rows.
   * If there are non-zero repeat count and if run
   * spans across row, first repeat and then continue.
   */
#ifdef  DEBUG
  MESG("\npkfont>> wd: %ld, ht: %ld, dyn_f: %d\n", wd, ht, dyn_f);
#endif
  for (np = 0, i = 0; i < ht; i++) {
    long  rowbits_left, nbits;

    repeat_count = 0;
    memset(rowptr, 0xff, rowbytes); /* 1 is white */
    rowbits_left = wd;
    /* Fill run left over from previous row */
    if (run_count > 0) {
      nbits = MIN(rowbits_left, run_count);
      switch (run_color) {
      case  0:
        rowbits_left -= fill_black_run(rowptr, 0, nbits);
        break;
      case  1:
        rowbits_left -= fill_white_run(rowptr, 0, nbits);
        break;
      }
      run_count -= nbits;
    }

    /* Read nybbles until we have a full row */
    while (np / 2 < pl && rowbits_left > 0) {
      int  nyb;

      nyb = (np % 2) ? dp[np/2] & 0x0f : (dp[np/2] >> 4) & 0x0f;
#if  DEBUG == 3
      MESG("\npk_nyb: %d", nyb);
#endif
      if (nyb == 14) { /* packed number "repeat_count" follows */
        if (repeat_count != 0)
          WARN("Second repeat count for this row!");
        np++; /* Consume this nybble */
        repeat_count = pk_packed_num(&np, dyn_f, dp, pl);
#if  DEBUG == 3
        MESG(" --> rep: %ld\n", repeat_count);
#endif
      } else if (nyb == 15) {
        if (repeat_count != 0)
          WARN("Second repeat count for this row!");
        np++; /* Consume this nybble */
        repeat_count = 1;
#if  DEBUG == 3
        MESG(" --> rep: %ld\n", repeat_count);
#endif
      } else { /* run_count */
        /* Interprete current nybble as packed number */
        run_count = pk_packed_num(&np, dyn_f, dp, pl);
#if  DEBUG == 3
        MESG(" --> run: %ld (%d)\n", run_count, run_color);
#endif
        nbits = MIN(rowbits_left, run_count);
        run_color  = !run_color;
        run_count -= nbits;
        switch (run_color) {
        case  0:
          rowbits_left -= fill_black_run(rowptr, wd - rowbits_left, nbits);
          break;
        case  1:
          rowbits_left -= fill_white_run(rowptr, wd - rowbits_left, nbits);
          break;
        }
      }
    }
    /* We got bitmap row data. */
#if  DEBUG == 2
    send_out(rowptr, rowbytes, wd, stream);
#else
    send_out(rowptr, rowbytes, stream);
#endif
    for ( ; i < ht && repeat_count > 0; repeat_count--, i++)
#if  DEBUG == 2
      send_out(rowptr, rowbytes, wd, stream);
#else
    send_out(rowptr, rowbytes, stream);
#endif
  }
  RELEASE(rowptr);

  return  0;
}
Example #3
0
void LoadPK(int32_t c, register struct char_entry * ptr)
{
  unsigned short   shrunk_width,shrunk_height;
  unsigned short   width,height;
  short   xoffset,yoffset;
  unsigned short   i_offset,j_offset;
  int   i,j,k,n;
  int   count=0;
  bool  paint_switch;
  unsigned char *pos,*buffer;

  DEBUG_PRINT(DEBUG_PK,("\n  LOAD PK CHAR\t%d",c));
  pos=ptr->pkdata;
  if ((ptr->flag_byte & 7) == 7) n=4;
  else if ((ptr->flag_byte & 4) == 4) n=2;
  else n=1;
  dyn_f = ptr->flag_byte / 16;
  paint_switch = ((ptr->flag_byte & 8) != 0);
  /*
   *  Read character preamble
   */
  if (n != 4) {
    ptr->tfmw = UNumRead(pos, 3);
    /* +n:   vertical escapement not used */
    pos+=3+n;
  } else {
    ptr->tfmw = UNumRead(pos, 4);
    /* +4:  horizontal escapement not used */
    /* +n:   vertical escapement not used */
    pos+=8+n;
  }
  DEBUG_PRINT(DEBUG_PK,(" %d",ptr->tfmw));
  ptr->tfmw = (dviunits)
    ((int64_t) ptr->tfmw * currentfont->s / 0x100000 );
  DEBUG_PRINT(DEBUG_PK,(" (%d)",ptr->tfmw));

  width   = UNumRead(pos, n);
  height  = UNumRead(pos+=n, n);
  DEBUG_PRINT(DEBUG_PK,(" %dx%d",width,height));

  if (width > 0x7fff || height > 0x7fff)
    Fatal("character %d too large in file %s", c, currentfont->name);

  /*
   * Hotspot issues: Shrinking to the topleft corner rather than the
     hotspot will displace glyphs a fraction of a pixel. We deal with
     this in as follows: The glyph is shrunk to its hotspot by
     offsetting the bitmap somewhat to put the hotspot in the lower
     left corner of a "shrink square". Shrinking to the topleft corner
     will then act as shrinking to the hotspot. This may enlarge the
     bitmap somewhat, of course.  (Also remember that the below
     calculation of i/j_offset is in integer arithmetics.)

     There will still be a displacement from rounding the dvi
     position, but vertically it will be equal for all glyphs on a
     line, so we displace a whole line vertically by fractions of a
     pixel. This is acceptible, IMHO. Sometime there will be support
     for subpixel positioning, horizontally. Will do for now, I
     suppose.
   */
  xoffset = SNumRead(pos+=n, n);
  i_offset = ( shrinkfactor - xoffset % shrinkfactor ) % shrinkfactor;
  width += i_offset;
  ptr->xOffset = xoffset+i_offset;

  yoffset = SNumRead(pos+=n, n);
  j_offset = ( shrinkfactor - (yoffset-(shrinkfactor-1)) % shrinkfactor )
    % shrinkfactor;
  height += j_offset;
  ptr->yOffset = yoffset+j_offset;

  DEBUG_PRINT(DEBUG_PK,(" (%dx%d)",width,height));
  /*
     Extra marginal so that we do not crop the image when shrinking.
  */
  shrunk_width = (width + shrinkfactor - 1) / shrinkfactor;
  shrunk_height = (height + shrinkfactor - 1) / shrinkfactor;
  ptr->w = shrunk_width;
  ptr->h = shrunk_height;
  pos+=n;
  if ((buffer = calloc(shrunk_width*shrunk_height*
											 shrinkfactor*shrinkfactor,sizeof(char)))==NULL)
    Fatal("cannot allocate space for pk buffer");
  DEBUG_PRINT(DEBUG_GLYPH,("\nDRAW GLYPH %d\n", (int)c));
  /* Raster char */
  if (dyn_f == 14) {	/* get raster by bits */
    int bitweight = 0;
    for (j = j_offset; j < (int) height; j++) {	/* get all rows */
      for (i = i_offset; i < (int) width; i++) {    /* get one row */
	bitweight /= 2;
	if (bitweight == 0) {
	  count = *pos++;
	  bitweight = 128;
	}
	if (count & bitweight) {
	  buffer[i+j*width]=1;
#ifdef DEBUG
	  DEBUG_PRINT(DEBUG_GLYPH,("+"));
	} else {
	  DEBUG_PRINT(DEBUG_GLYPH,(" "));
#endif
	}
      }
      DEBUG_PRINT(DEBUG_GLYPH,("|\n"));
    }
  } else {		/* get packed raster */
    poshalf=0;
    repeatcount = 0;
    for(i=i_offset, j=j_offset; j<height; ) {
      count = pk_packed_num(&pos);
      while (count > 0) {
	if (i+count < width) {
	  if (paint_switch)
	    for(k=0;k<count;k++) {
	      buffer[k+i+j*width]=1;
	      DEBUG_PRINT(DEBUG_GLYPH,("*"));
	    }
#ifdef DEBUG
	  else for(k=0;k<count;k++)
	    DEBUG_PRINT(DEBUG_GLYPH,(" "));
#endif
	  i += count;
	  count = 0;
	} else {
	  if (paint_switch)
	    for(k=i;k<width;k++) {
	      buffer[k+j*width]=1;
	      DEBUG_PRINT(DEBUG_GLYPH,("#"));
	    }
#ifdef DEBUG
	  else for(k=i;k<width;k++)
	    DEBUG_PRINT(DEBUG_GLYPH,(" "));
#endif
	  DEBUG_PRINT(DEBUG_GLYPH,("|\n"));
	  j++;
	  count -= width-i;
	  /* Repeat row(s) */
	  for (;repeatcount>0; repeatcount--,j++) {
	    for (i = i_offset; i<width; i++) {
	      buffer[i+j*width]=buffer[i+(j-1)*width];
#ifdef DEBUG
	      if (buffer[i+j*width]>0) {
		DEBUG_PRINT(DEBUG_GLYPH,("="));
	      } else {
		DEBUG_PRINT(DEBUG_GLYPH,(" "));
	      }
#endif
	    }
	    DEBUG_PRINT(DEBUG_GLYPH,("|\n"));
	  }
	  i=i_offset;
	}
      }
      paint_switch = 1 - paint_switch;
    }
    if (i>i_offset)
      Fatal("wrong number of bits stored: char. %c, font %s",
	    (char)c, currentfont->name);
    if (j>height)
      Fatal("bad PK file %s, too many bits", currentfont->name);
  }
  /*
    Shrink raster while doing antialiasing. (See above. The
    single-glyph output seems better than what xdvi at 300 dpi,
    shrinkfactor 3 produces.)
  */
  if ((ptr->data = calloc(shrunk_width*shrunk_height,sizeof(char))) == NULL)
    Fatal("unable to malloc image space for char %c", (char)c);
  for (j = 0; j < (int) height; j++) {
    for (i = 0; i < (int) width; i++) {
      /* if (((i % shrinkfactor) == 0) && ((j % shrinkfactor) == 0))
	 ptr->data[i/shrinkfactor+j/shrinkfactor*shrunk_width] =
	 buffer[i+j*width];
	 else */
      ptr->data[i/shrinkfactor+j/shrinkfactor*shrunk_width] +=
	buffer[i+j*width];
    }
  }
  for (j = 0; j < shrunk_height; j++) {
    for (i = 0; i < shrunk_width; i++) {
      ptr->data[i+j*shrunk_width] = ptr->data[i+j*shrunk_width]
	*255/shrinkfactor/shrinkfactor;
      DEBUG_PRINT(DEBUG_GLYPH,("%3u ",ptr->data[i+j*shrunk_width]));
    }
    DEBUG_PRINT(DEBUG_GLYPH,("|\n"));
  }
  free(buffer);
}