BITMAP    *bitmap_convert_msb8(Uchar *data, int w, int h, int stride)
{
    BITMAP    *bm;
    Uchar    *unit;
    Uchar    *curr;
    int    i;
    int    bytes;
    
    bm = bitmap_alloc(w, h);
    bytes = ROUND(w, 8);
    unit = (Uchar *)bm->data;
    curr = data;
    for(i = 0; i < h; i++) {
#ifdef WORD_LITTLE_ENDIAN
        int    j;
        
        for(j = 0; j < bytes; curr++, j++)
            unit[j] = bit_swap[*curr];
        curr += stride - bytes;
#else
        memcpy(unit, curr, bytes);
        curr += stride;
#endif
        memset(unit + bytes, 0, bm->stride - bytes);
        unit += bm->stride;
    }
    if(SHOW_OP_DATA)
        bitmap_print(stderr, bm);
    return bm;
}
BITMAP    *bitmap_convert_lsb8(Uchar *bits, int w, int h, int stride)
{
    BITMAP    *bm;
    int    i;
    Uchar    *unit;
    register Uchar *curr;
    int    bytes;
    
    DEBUG((DBG_BITMAP_OPS, "convert LSB %dx%d@8 -> bitmap\n", w, h));    

    bm = bitmap_alloc_raw(w, h);

    /* this is the number of bytes in the original bitmap */
    bytes = ROUND(w, 8);
    unit  = (Uchar *)bm->data;
    curr = bits;
    /* we try to do this as fast as we can */    
    for(i = 0; i < h; i++) {
#ifdef WORD_LITTLE_ENDIAN
        memcpy(unit, curr, bytes);
        curr += stride;
#else
        int    j;
        
        for(j = 0; j < bytes; curr++, j++)
            unit[j] = bit_swap[*curr];
        curr += stride - bytes;
#endif
        memset(unit + bytes, 0, bm->stride - bytes);
        unit  += bm->stride;
    }
    if(SHOW_OP_DATA)
        bitmap_print(stderr, bm);
    return bm;
}
Beispiel #3
0
int
main(int argc, char **argv)
{
	char buffer[512];
	bitmap_t bmap;

	#define BSIZE 64-9
	
	memset((void *) buffer, 0xff, 512);
	bmap = (bitmap_t) buffer;
	
	printf("0x00000000 bitmap:\n");
	bitmap_zero(bmap, BSIZE);
	bitmap_print(bmap, BSIZE);
	printf("Is empty? %s\n", bitmap_empty(bmap, BSIZE) ? "Y" : "N");

	bitmap_set_region(bmap, 0, 2);
	bitmap_print(bmap, BSIZE);
	
	return 0;
}
void    bitmap_flip_rotate_counter_clockwise(BITMAP *bm)
{
    BITMAP    nb;
    BmUnit    *fptr, *tptr;
    BmUnit    fmask, tmask;
    int    w, h;
    
    nb.width = bm->height;
    nb.height = bm->width;
    nb.stride = BM_BYTES_PER_LINE(&nb);
    nb.data = mdvi_calloc(nb.height, nb.stride);
    
    fptr = bm->data;
    tptr = nb.data;
    tmask = FIRSTMASK;
    
    for(h = 0; h < bm->height; h++) {
        BmUnit    *fline, *tline;

        fmask = FIRSTMASK;
        fline = fptr;
        tline = tptr;
        for(w = 0; w < bm->width; w++) {
            if(*fline & fmask)
                *tline |= tmask;
            if(fmask == LASTMASK) {
                fmask = FIRSTMASK;
                fline++;
            } else
                NEXTMASK(fmask);
            /* go to next line */
            tline = bm_offset(tline, nb.stride);
        }
        fptr = bm_offset(fptr, bm->stride);
        if(tmask == LASTMASK) {
            tmask = FIRSTMASK;
            tptr++;
        } else
            NEXTMASK(tmask);
    }

    DEBUG((DBG_BITMAP_OPS, "flip_rotate_counter_clockwise (%d,%d) -> (%d,%d)\n",
        bm->width, bm->height, nb.width, nb.height));
    mdvi_free(bm->data);
    bm->data = nb.data;
    bm->width = nb.width;
    bm->height = nb.height;    
    bm->stride = nb.stride;
    if(SHOW_OP_DATA)
        bitmap_print(stderr, bm);
}
void    bitmap_flip_diagonally(BITMAP *bm)
{
    BITMAP    nb;
    BmUnit    *fptr, *tptr;
    BmUnit    fmask, tmask;
    int    w, h;
    
    nb.width = bm->width;
    nb.height = bm->height;
    nb.stride = bm->stride;
    nb.data = mdvi_calloc(bm->height, bm->stride);
    
    fptr = bm->data;
    tptr = __bm_unit_ptr(&nb, nb.width-1, nb.height-1);
    for(h = 0; h < bm->height; h++) {
        BmUnit    *fline, *tline;
        
        fline = fptr; 
        tline = tptr;
        fmask = FIRSTMASK;
        tmask = FIRSTMASKAT(nb.width-1);
        for(w = 0; w < bm->width; w++) {
            if(*fline & fmask)
                *tline |= tmask;
            if(fmask == LASTMASK) {
                fmask = FIRSTMASK;
                fline++;
            } else
                NEXTMASK(fmask);
            if(tmask == FIRSTMASK) {
                tmask = LASTMASK;
                tline--;
            } else
                PREVMASK(tmask);
        }
        fptr = bm_offset(fptr, bm->stride);
        tptr = bm_offset(tptr, -nb.stride);
    }
    DEBUG((DBG_BITMAP_OPS, "flip_diagonally (%d,%d) -> (%d,%d)\n",
        bm->width, bm->height, nb.width, nb.height));
    mdvi_free(bm->data);
    bm->data = nb.data;
    if(SHOW_OP_DATA)
        bitmap_print(stderr, bm);
}
Beispiel #6
0
int main(void)
{
    bitmap_t bitmap = bitmap_allocate(6);
    if (bitmap == NULL)
        exit(EXIT_FAILURE);

    int i;
    for (i = 0; i < 3; i++) {
        bitmap_setbit(bitmap, i);
    }
    
    // Check up to 3 digits
    print_result(bitmap_alltrue(bitmap, 3));
    
    // Check up all digits
    print_result(bitmap_alltrue(bitmap, 0));

    bitmap_print(bitmap);
    
    bitmap_destroy(&bitmap);
    return (EXIT_SUCCESS);
}
Beispiel #7
0
static void
print_rtx (rtx in_rtx)
{
  int i = 0;
  int j;
  const char *format_ptr;
  int is_insn;

  if (sawclose)
    {
      if (flag_simple)
        fputc (' ', outfile);
      else
        fprintf (outfile, "\n%s%*s", print_rtx_head, indent * 2, "");
      sawclose = 0;
    }

  if (in_rtx == 0)
    {
      fputs ("(nil)", outfile);
      sawclose = 1;
      return;
    }
  else if (GET_CODE (in_rtx) > NUM_RTX_CODE)
    {
       fprintf (outfile, "(??? bad code %d\n)", GET_CODE (in_rtx));
       sawclose = 1;
       return;
    }

  is_insn = INSN_P (in_rtx);

  /* When printing in VCG format we write INSNs, NOTE, LABEL, and BARRIER
     in separate nodes and therefore have to handle them special here.  */
  if (dump_for_graph
      && (is_insn || NOTE_P (in_rtx)
          || LABEL_P (in_rtx) || BARRIER_P (in_rtx)))
    {
      i = 3;
      indent = 0;
    }
  else
    {
      /* Print name of expression code.  */
      if (flag_simple && GET_CODE (in_rtx) == CONST_INT)
        fputc ('(', outfile);
      else
        fprintf (outfile, "(%s", GET_RTX_NAME (GET_CODE (in_rtx)));

      if (! flag_simple)
        {
          if (RTX_FLAG (in_rtx, in_struct))
            fputs ("/s", outfile);

          if (RTX_FLAG (in_rtx, volatil))
            fputs ("/v", outfile);

          if (RTX_FLAG (in_rtx, unchanging))
            fputs ("/u", outfile);

          if (RTX_FLAG (in_rtx, frame_related))
            fputs ("/f", outfile);

          if (RTX_FLAG (in_rtx, jump))
            fputs ("/j", outfile);

          if (RTX_FLAG (in_rtx, call))
            fputs ("/c", outfile);

          if (RTX_FLAG (in_rtx, return_val))
            fputs ("/i", outfile);

          /* Print REG_NOTE names for EXPR_LIST and INSN_LIST.  */
          if (GET_CODE (in_rtx) == EXPR_LIST
              || GET_CODE (in_rtx) == INSN_LIST)
            fprintf (outfile, ":%s",
                     GET_REG_NOTE_NAME (GET_MODE (in_rtx)));

          /* For other rtl, print the mode if it's not VOID.  */
          else if (GET_MODE (in_rtx) != VOIDmode)
            fprintf (outfile, ":%s", GET_MODE_NAME (GET_MODE (in_rtx)));
        }
    }

#ifndef GENERATOR_FILE
  if (GET_CODE (in_rtx) == CONST_DOUBLE && FLOAT_MODE_P (GET_MODE (in_rtx)))
    i = 5;
#endif

  /* Get the format string and skip the first elements if we have handled
     them already.  */
  format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx)) + i;
  for (; i < GET_RTX_LENGTH (GET_CODE (in_rtx)); i++)
    switch (*format_ptr++)
      {
        const char *str;

      case 'T':
        str = XTMPL (in_rtx, i);
        goto string;

      case 'S':
      case 's':
        str = XSTR (in_rtx, i);
      string:

        if (str == 0)
          fputs (dump_for_graph ? " \\\"\\\"" : " \"\"", outfile);
        else
          {
            if (dump_for_graph)
              fprintf (outfile, " (\\\"%s\\\")", str);
            else
              fprintf (outfile, " (\"%s\")", str);
          }
        sawclose = 1;
        break;

        /* 0 indicates a field for internal use that should not be printed.
           An exception is the third field of a NOTE, where it indicates
           that the field has several different valid contents.  */
      case '0':
        if (i == 1 && REG_P (in_rtx))
          {
            if (REGNO (in_rtx) != ORIGINAL_REGNO (in_rtx))
              fprintf (outfile, " [%d]", ORIGINAL_REGNO (in_rtx));
          }
#ifndef GENERATOR_FILE
        else if (i == 1 && GET_CODE (in_rtx) == SYMBOL_REF)
          {
            int flags = SYMBOL_REF_FLAGS (in_rtx);
            if (flags)
              fprintf (outfile, " [flags 0x%x]", flags);
          }
        else if (i == 2 && GET_CODE (in_rtx) == SYMBOL_REF)
          {
            tree decl = SYMBOL_REF_DECL (in_rtx);
            if (decl)
              print_node_brief (outfile, "", decl, 0);
          }
#endif
        else if (i == 4 && NOTE_P (in_rtx))
          {
            switch (NOTE_LINE_NUMBER (in_rtx))
              {
              case NOTE_INSN_EH_REGION_BEG:
              case NOTE_INSN_EH_REGION_END:
                if (flag_dump_unnumbered)
                  fprintf (outfile, " #");
                else
                  fprintf (outfile, " %d", NOTE_EH_HANDLER (in_rtx));
                sawclose = 1;
                break;

              case NOTE_INSN_BLOCK_BEG:
              case NOTE_INSN_BLOCK_END:
#ifndef GENERATOR_FILE
                dump_addr (outfile, " ", NOTE_BLOCK (in_rtx));
#endif
                sawclose = 1;
                break;

              case NOTE_INSN_BASIC_BLOCK:
                {
#ifndef GENERATOR_FILE
                  basic_block bb = NOTE_BASIC_BLOCK (in_rtx);
                  if (bb != 0)
                    fprintf (outfile, " [bb %d]", bb->index);
#endif
                  break;
                }

              case NOTE_INSN_EXPECTED_VALUE:
                indent += 2;
                if (!sawclose)
                  fprintf (outfile, " ");
                print_rtx (NOTE_EXPECTED_VALUE (in_rtx));
                indent -= 2;
                break;

              case NOTE_INSN_DELETED_LABEL:
                {
                  const char *label = NOTE_DELETED_LABEL_NAME (in_rtx);
                  if (label)
                    fprintf (outfile, " (\"%s\")", label);
                  else
                    fprintf (outfile, " \"\"");
                }
                break;

              case NOTE_INSN_SWITCH_TEXT_SECTIONS:
                {
#ifndef GENERATOR_FILE
                  basic_block bb = NOTE_BASIC_BLOCK (in_rtx);
                  if (bb != 0)
                    fprintf (outfile, " [bb %d]", bb->index);
#endif
                  break;
                }
                
              case NOTE_INSN_VAR_LOCATION:
#ifndef GENERATOR_FILE
                fprintf (outfile, " (");
                print_mem_expr (outfile, NOTE_VAR_LOCATION_DECL (in_rtx));
                fprintf (outfile, " ");
                print_rtx (NOTE_VAR_LOCATION_LOC (in_rtx));
                fprintf (outfile, ")");
#endif
                break;

              default:
                {
                  const char * const str = X0STR (in_rtx, i);

                  if (NOTE_LINE_NUMBER (in_rtx) < 0)
                    ;
                  else if (str == 0)
                    fputs (dump_for_graph ? " \\\"\\\"" : " \"\"", outfile);
                  else
                    {
                      if (dump_for_graph)
                        fprintf (outfile, " (\\\"%s\\\")", str);
                      else
                        fprintf (outfile, " (\"%s\")", str);
                    }
                  break;
                }
              }
          }
        break;

      case 'e':
      do_e:
        indent += 2;
        if (!sawclose)
          fprintf (outfile, " ");
        print_rtx (XEXP (in_rtx, i));
        indent -= 2;
        break;

      case 'E':
      case 'V':
        indent += 2;
        if (sawclose)
          {
            fprintf (outfile, "\n%s%*s",
                     print_rtx_head, indent * 2, "");
            sawclose = 0;
          }
        fputs (" [", outfile);
        if (NULL != XVEC (in_rtx, i))
          {
            indent += 2;
            if (XVECLEN (in_rtx, i))
              sawclose = 1;

            for (j = 0; j < XVECLEN (in_rtx, i); j++)
              print_rtx (XVECEXP (in_rtx, i, j));

            indent -= 2;
          }
        if (sawclose)
          fprintf (outfile, "\n%s%*s", print_rtx_head, indent * 2, "");

        fputs ("]", outfile);
        sawclose = 1;
        indent -= 2;
        break;

      case 'w':
        if (! flag_simple)
          fprintf (outfile, " ");
        fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, XWINT (in_rtx, i));
        if (! flag_simple)
          fprintf (outfile, " [" HOST_WIDE_INT_PRINT_HEX "]",
                   XWINT (in_rtx, i));
        break;

      case 'i':
        if (i == 4 && INSN_P (in_rtx))
          {
#ifndef GENERATOR_FILE
            /*  Pretty-print insn locators.  Ignore scoping as it is mostly
                redundant with line number information and do not print anything
                when there is no location information available.  */
            if (INSN_LOCATOR (in_rtx) && insn_file (in_rtx))
              fprintf(outfile, " %s:%i", insn_file (in_rtx), insn_line (in_rtx));
#endif
          }
        else if (i == 6 && NOTE_P (in_rtx))
          {
            /* This field is only used for NOTE_INSN_DELETED_LABEL, and
               other times often contains garbage from INSN->NOTE death.  */
            if (NOTE_LINE_NUMBER (in_rtx) == NOTE_INSN_DELETED_LABEL)
              fprintf (outfile, " %d",  XINT (in_rtx, i));
          }
        else
          {
            int value = XINT (in_rtx, i);
            const char *name;

#ifndef GENERATOR_FILE
            if (REG_P (in_rtx) && value < FIRST_PSEUDO_REGISTER)
              fprintf (outfile, " %d %s", REGNO (in_rtx),
                       reg_names[REGNO (in_rtx)]);
            else if (REG_P (in_rtx)
                     && value <= LAST_VIRTUAL_REGISTER)
              {
                if (value == VIRTUAL_INCOMING_ARGS_REGNUM)
                  fprintf (outfile, " %d virtual-incoming-args", value);
                else if (value == VIRTUAL_STACK_VARS_REGNUM)
                  fprintf (outfile, " %d virtual-stack-vars", value);
                else if (value == VIRTUAL_STACK_DYNAMIC_REGNUM)
                  fprintf (outfile, " %d virtual-stack-dynamic", value);
                else if (value == VIRTUAL_OUTGOING_ARGS_REGNUM)
                  fprintf (outfile, " %d virtual-outgoing-args", value);
                else if (value == VIRTUAL_CFA_REGNUM)
                  fprintf (outfile, " %d virtual-cfa", value);
                else
                  fprintf (outfile, " %d virtual-reg-%d", value,
                           value-FIRST_VIRTUAL_REGISTER);
              }
            else
#endif
              if (flag_dump_unnumbered
                     && (is_insn || NOTE_P (in_rtx)))
              fputc ('#', outfile);
            else
              fprintf (outfile, " %d", value);

#ifndef GENERATOR_FILE
            if (REG_P (in_rtx) && REG_ATTRS (in_rtx))
              {
                fputs (" [", outfile);
                if (ORIGINAL_REGNO (in_rtx) != REGNO (in_rtx))
                  fprintf (outfile, "orig:%i", ORIGINAL_REGNO (in_rtx));
                if (REG_EXPR (in_rtx))
                  print_mem_expr (outfile, REG_EXPR (in_rtx));

                if (REG_OFFSET (in_rtx))
                  fprintf (outfile, "+" HOST_WIDE_INT_PRINT_DEC,
                           REG_OFFSET (in_rtx));
                fputs (" ]", outfile);
              }
#endif

            if (is_insn && &INSN_CODE (in_rtx) == &XINT (in_rtx, i)
                && XINT (in_rtx, i) >= 0
                && (name = get_insn_name (XINT (in_rtx, i))) != NULL)
              fprintf (outfile, " {%s}", name);
            sawclose = 0;
          }
        break;

      /* Print NOTE_INSN names rather than integer codes.  */

      case 'n':
        if (XINT (in_rtx, i) >= (int) NOTE_INSN_BIAS
            && XINT (in_rtx, i) < (int) NOTE_INSN_MAX)
          fprintf (outfile, " %s", GET_NOTE_INSN_NAME (XINT (in_rtx, i)));
        else
          fprintf (outfile, " %d", XINT (in_rtx, i));
        sawclose = 0;
        break;

      case 'u':
        if (XEXP (in_rtx, i) != NULL)
          {
            rtx sub = XEXP (in_rtx, i);
            enum rtx_code subc = GET_CODE (sub);

            if (GET_CODE (in_rtx) == LABEL_REF)
              {
                if (subc == NOTE
                    && NOTE_LINE_NUMBER (sub) == NOTE_INSN_DELETED_LABEL)
                  {
                    if (flag_dump_unnumbered)
                      fprintf (outfile, " [# deleted]");
                    else
                      fprintf (outfile, " [%d deleted]", INSN_UID (sub));
                    sawclose = 0;
                    break;
                  }

                if (subc != CODE_LABEL)
                  goto do_e;
              }

            if (flag_dump_unnumbered)
              fputs (" #", outfile);
            else
              fprintf (outfile, " %d", INSN_UID (sub));
          }
        else
          fputs (" 0", outfile);
        sawclose = 0;
        break;

      case 'b':
#ifndef GENERATOR_FILE
        if (XBITMAP (in_rtx, i) == NULL)
          fputs (" {null}", outfile);
        else
          bitmap_print (outfile, XBITMAP (in_rtx, i), " {", "}");
#endif
        sawclose = 0;
        break;

      case 't':
#ifndef GENERATOR_FILE
        dump_addr (outfile, " ", XTREE (in_rtx, i));
#endif
        break;

      case '*':
        fputs (" Unknown", outfile);
        sawclose = 0;
        break;

      case 'B':
#ifndef GENERATOR_FILE
        if (XBBDEF (in_rtx, i))
          fprintf (outfile, " %i", XBBDEF (in_rtx, i)->index);
#endif
        break;

      default:
        gcc_unreachable ();
      }

  switch (GET_CODE (in_rtx))
    {
#ifndef GENERATOR_FILE
    case MEM:
      fprintf (outfile, " [" HOST_WIDE_INT_PRINT_DEC, MEM_ALIAS_SET (in_rtx));

      if (MEM_EXPR (in_rtx))
        print_mem_expr (outfile, MEM_EXPR (in_rtx));

      if (MEM_OFFSET (in_rtx))
        fprintf (outfile, "+" HOST_WIDE_INT_PRINT_DEC,
                 INTVAL (MEM_OFFSET (in_rtx)));

      if (MEM_SIZE (in_rtx))
        fprintf (outfile, " S" HOST_WIDE_INT_PRINT_DEC,
                 INTVAL (MEM_SIZE (in_rtx)));

      if (MEM_ALIGN (in_rtx) != 1)
        fprintf (outfile, " A%u", MEM_ALIGN (in_rtx));

      fputc (']', outfile);
      break;

    case CONST_DOUBLE:
      if (FLOAT_MODE_P (GET_MODE (in_rtx)))
        {
          char s[60];

          real_to_decimal (s, CONST_DOUBLE_REAL_VALUE (in_rtx),
                           sizeof (s), 0, 1);
          fprintf (outfile, " %s", s);

          real_to_hexadecimal (s, CONST_DOUBLE_REAL_VALUE (in_rtx),
                               sizeof (s), 0, 1);
          fprintf (outfile, " [%s]", s);
        }
      break;
#endif

    case CODE_LABEL:
      fprintf (outfile, " [%d uses]", LABEL_NUSES (in_rtx));
      switch (LABEL_KIND (in_rtx))
        {
          case LABEL_NORMAL: break;
          case LABEL_STATIC_ENTRY: fputs (" [entry]", outfile); break;
          case LABEL_GLOBAL_ENTRY: fputs (" [global entry]", outfile); break;
          case LABEL_WEAK_ENTRY: fputs (" [weak entry]", outfile); break;
          default: gcc_unreachable ();
        }
      break;

    default:
      break;
    }

  if (dump_for_graph
      && (is_insn || NOTE_P (in_rtx)
          || LABEL_P (in_rtx) || BARRIER_P (in_rtx)))
    sawclose = 0;
  else
    {
      fputc (')', outfile);
      sawclose = 1;
    }
}
Beispiel #8
0
static int load_one_glyph(DviContext *dvi, DviFont *font, int code)
{
    BITMAP *map;
    DviFontChar *ch;
    int    status;

#ifndef NODEBUG
    ch = FONTCHAR(font, code);
    DEBUG((DBG_GLYPHS, "loading glyph code %d in %s (at %u)\n",
        code, font->fontname, ch->offset));
#endif
    if(font->finfo->getglyph == NULL) {
        /* font type does not need to load glyphs (e.g. vf) */
        return 0;
    }

    status = font->finfo->getglyph(&dvi->params, font, code);
    if(status < 0)
        return -1;
    /* get the glyph again (font->chars may have changed) */
    ch = FONTCHAR(font, code);
#ifndef NODEBUG
    map = (BITMAP *)ch->glyph.data;
    if(DEBUGGING(BITMAP_DATA)) {
        DEBUG((DBG_BITMAP_DATA,
            "%s: new %s bitmap for character %d:\n",
            font->fontname, TYPENAME(font), code));
        if(MDVI_GLYPH_ISEMPTY(map))
            DEBUG((DBG_BITMAP_DATA, "blank bitmap\n"));
        else
            bitmap_print(stderr, map);
    }
#endif
    /* check if we have to scale it */
    if(!font->finfo->scalable && font->hdpi != font->vdpi) {
        int    hs, vs, d;
        
        /* we scale it ourselves */
        d = Max(font->hdpi, font->vdpi);
        hs = d / font->hdpi;
        vs = d / font->vdpi;
        if(ch->width && ch->height && (hs > 1 || vs > 1)) {
            int    h, v;
            DviGlyph glyph;
            
            DEBUG((DBG_FONTS, 
                "%s: scaling glyph %d to resolution %dx%d\n",
                font->fontname, code, font->hdpi, font->vdpi));
            h = dvi->params.hshrink;
            v = dvi->params.vshrink;
            d = dvi->params.density;
            dvi->params.hshrink = hs;
            dvi->params.vshrink = vs;
            dvi->params.density = 50;
            /* shrink it */
            font->finfo->shrink0(dvi, font, ch, &glyph);
            /* restore parameters */
            dvi->params.hshrink = h;
            dvi->params.vshrink = v;
            dvi->params.density = d;
            /* update glyph data */
            if(!MDVI_GLYPH_ISEMPTY(ch->glyph.data))
                bitmap_destroy((BITMAP *)ch->glyph.data);
            ch->glyph.data = glyph.data;
            ch->glyph.x = glyph.x;
            ch->glyph.y = glyph.y;
            ch->glyph.w = glyph.w;
            ch->glyph.h = glyph.h;
        }
            
    }
    font_transform_glyph(dvi->params.orientation, &ch->glyph);
        
    return 0;
}
void    mdvi_shrink_glyph(DviContext *dvi, DviFont *font,
    DviFontChar *pk, DviGlyph *dest)
{
    int    rows_left, rows, init_cols;
    int    cols_left, cols;
    BmUnit    *old_ptr, *new_ptr;
    BITMAP    *oldmap, *newmap;
    BmUnit    m, *cp;
    DviGlyph *glyph;
    int    sample, min_sample;
    int    old_stride;
    int    new_stride;
    int    x, y;
    int    w, h;
    int    hs, vs;
    
    hs = dvi->params.hshrink;
    vs = dvi->params.vshrink;
    
    min_sample = vs * hs * dvi->params.density / 100;

    glyph = &pk->glyph;
    oldmap = (BITMAP *)glyph->data;
        
    x = (int)glyph->x / hs;
    init_cols = (int)glyph->x - x * hs;
    if(init_cols <= 0)
        init_cols += hs;
    else
        x++;
    w = x + ROUND((int)glyph->w - glyph->x, hs);

    cols = (int)glyph->y + 1;
    y = cols / vs;
    rows = cols - y * vs;
    if(rows <= 0) {
        rows += vs;
        y--;
    }
    h = y + ROUND((int)glyph->h - cols, vs) + 1;

    /* create the new glyph */
    newmap = bitmap_alloc(w, h);
    dest->data = newmap;
    dest->x = x;
    dest->y = glyph->y / vs;
    dest->w = w;
    dest->h = h;

    old_ptr = oldmap->data;
    old_stride = oldmap->stride;
    new_ptr = newmap->data;
    new_stride = newmap->stride;
    rows_left = glyph->h;

    while(rows_left) {
        if(rows > rows_left)
            rows = rows_left;
        cols_left = glyph->w;
        m = FIRSTMASK;
        cp = new_ptr;
        cols = init_cols;
        while(cols_left > 0) {
            if(cols > cols_left)
                cols = cols_left;
            sample = do_sample(old_ptr, old_stride,
                glyph->w - cols_left, cols, rows);
            if(sample >= min_sample)
                *cp |= m;
            if(m == LASTMASK) {
                m = FIRSTMASK;
                cp++;
            } else
                NEXTMASK(m);
            cols_left -= cols;
            cols = hs;
        }
        new_ptr = bm_offset(new_ptr, new_stride);
        old_ptr = bm_offset(old_ptr, rows * old_stride);
        rows_left -= rows;
        rows = vs;
    }    
    DEBUG((DBG_BITMAPS, "shrink_glyph: (%dw,%dh,%dx,%dy) -> (%dw,%dh,%dx,%dy)\n",
        glyph->w, glyph->h, glyph->x, glyph->y,
        dest->w, dest->h, dest->x, dest->y));
    if(DEBUGGING(BITMAP_DATA))
        bitmap_print(stderr, newmap);
}