src/raster.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. VF_OutlineToBitmap
  2. vf_outline_to_bitmap
  3. vf_draw_outline
  4. read_xy
  5. draw_arc
  6. draw_bezier
  7. trace_outline
  8. fill_edges

   1 /*
   2  * raster.c - a rasterizer for outline data
   3  * by Hirotsugu Kakugawa
   4  *
   5  */
   6 /*
   7  * Copyright (C) 1993-1997 Hirotsugu Kakugawa. 
   8  * All rights reserved.
   9  *
  10  * This file is part of the VFlib Library.  This library is free
  11  * software; you can redistribute it and/or modify it under the terms of
  12  * the GNU Library General Public License as published by the Free
  13  * Software Foundation; either version 2 of the License, or (at your
  14  * option) any later version.  This library is distributed in the hope
  15  * that it will be useful, but WITHOUT ANY WARRANTY; without even the
  16  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  17  * PURPOSE.  See the GNU Library General Public License for more details.
  18  * You should have received a copy of the GNU Library General Public
  19  * License along with this library; if not, write to the Free Software
  20  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21  */
  22 
  23 #include <stdio.h>
  24 #include <stdlib.h>
  25 #ifdef HAVE_UNISTD_H
  26 #  include <unistd.h>
  27 #endif
  28 #include <math.h>
  29 #include "config.h"
  30 #include "VFlib-3_6.h"
  31 #include "VFsys.h"
  32 #include "consts.h"
  33 #include "bitmap.h"
  34 
  35 
  36 Private VF_BITMAP  Vbm;
  37 Private int        Vmax_width, Vmax_height;
  38 Private VF_OUTLINE_ELEM  read_xy(int*,int*,VF_OUTLINE_ELEM**,VF_OUTLINE_ELEM);
  39 Private void             draw_arc(int*,int*,void(*)());
  40 Private void             draw_bezier(int*,int*,void(*)());
  41 Private void             fill_edges(), trace_outline();
  42 
  43 #ifndef M_PI
  44 #  define M_PI     3.14159265358979323846
  45 #endif
  46 #define ARC_DIV    8
  47 #define BEZ_DIV    8
  48 
  49 
  50 static unsigned char  flip[] = {
  51   0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
  52 static unsigned char bit_table[] = {
  53   0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
  54 
  55 
  56 /**
  57  **   VF_Outline2Bitmap
  58  **/
  59 Public VF_BITMAP
  60 VF_OutlineToBitmap(VF_OUTLINE outline, 
     /* [<][>][^][v][top][bottom][index][help] */
  61                    double dpi_x, double dpi_y, 
  62                    double point_size, double mag_x, double mag_y)
  63 {
  64   vf_error = 0;
  65   return vf_outline_to_bitmap(outline, dpi_x, dpi_y,
  66                               point_size, mag_x, mag_y);
  67 }
  68 
  69 Glocal VF_BITMAP
  70 vf_outline_to_bitmap(VF_OUTLINE outline, 
     /* [<][>][^][v][top][bottom][index][help] */
  71                      double dpi_x, double dpi_y, 
  72                      double point_size, double mag_x, double mag_y)
  73 {
  74   double     bbx_w, bbx_h;
  75   VF_BITMAP  bm;
  76 
  77   if (outline == NULL)
  78     return NULL;
  79 
  80   bbx_w = mag_x * (double)outline[VF_OL_HEADER_INDEX_MAX_X] 
  81           / (double)outline[VF_OL_HEADER_INDEX_EM];
  82   bbx_h = mag_y * (double)outline[VF_OL_HEADER_INDEX_MAX_Y]
  83           / (double)outline[VF_OL_HEADER_INDEX_EM];
  84   if (point_size >= 0){
  85     bbx_w *= point_size;
  86     bbx_h *= point_size;
  87   } else {
  88     bbx_w *= VF_OL_HEADER_DECODE(outline[VF_OL_HEADER_INDEX_POINT_SIZE]);
  89     bbx_h *= VF_OL_HEADER_DECODE(outline[VF_OL_HEADER_INDEX_POINT_SIZE]);
  90   }
  91   if ((dpi_x >= 0) && (dpi_y >= 0)){
  92     bbx_w *= (dpi_x / 72.27);
  93     bbx_h *= (dpi_y / 72.27);
  94   } else {
  95     bbx_w *= (VF_OL_HEADER_DECODE(outline[VF_OL_HEADER_INDEX_DPI_X]) / 72.27);
  96     bbx_h *= (VF_OL_HEADER_DECODE(outline[VF_OL_HEADER_INDEX_DPI_Y]) / 72.27);
  97   }
  98 
  99   if ((bm = vf_alloc_bitmap((int)ceil(bbx_w), (int)ceil(bbx_h))) == NULL)
 100     return NULL;
 101 
 102   bm->off_x = toint(0 - bbx_w * (double)outline[VF_OL_HEADER_INDEX_REF_X] 
 103                     / (double)outline[VF_OL_HEADER_INDEX_MAX_X]);
 104   bm->off_y = toint(bbx_h * (double)outline[VF_OL_HEADER_INDEX_REF_Y] 
 105                     / (double)outline[VF_OL_HEADER_INDEX_MAX_Y]);
 106   bm->mv_x  = toint(bbx_w * (double)outline[VF_OL_HEADER_INDEX_MV_X] 
 107                     / (double)outline[VF_OL_HEADER_INDEX_MAX_X]);
 108   bm->mv_y  = toint(bbx_h * (double)outline[VF_OL_HEADER_INDEX_MV_Y] 
 109                     / (double)outline[VF_OL_HEADER_INDEX_MAX_Y]);
 110 #if 0
 111   printf(">>DEV: %f %f %fpt\n",
 112          dev_dpi_x, dev_dpi_y, point_size);
 113   printf(">>BBX: (%fx%f) \n", bbx_w, bbx_h);
 114   printf(">>BM BBX: (%dx%d) \n", bm->bbx_width, bm->bbx_height);
 115   printf(">>OFF: (%d,%d)  MV: (%d,%d)\n", 
 116     bm->off_x, bm->off_y, bm->mv_x, bm->mv_y);
 117 #endif
 118 
 119   if (vf_draw_outline(bm, outline) < 0){
 120     vf_free_bitmap(bm);
 121     return NULL;
 122   }
 123   return bm;
 124 }
 125 
 126 Glocal int
 127 vf_draw_outline(VF_BITMAP bm, VF_OUTLINE outline)
     /* [<][>][^][v][top][bottom][index][help] */
 128 {
 129   int              x[4], y[4], f;
 130   VF_OUTLINE_ELEM  *olp, token;
 131   Private void    (*func_table[])() = {fill_edges, trace_outline};
 132 
 133   Vbm         = bm; 
 134   Vmax_width  = outline[VF_OL_HEADER_INDEX_MAX_X];
 135   Vmax_height = outline[VF_OL_HEADER_INDEX_MAX_Y];
 136   for (f = 0; f <= 1; f++){
 137     olp = &outline[VF_OL_OUTLINE_HEADER_SIZE_TYPE0];
 138     token = *(olp++);
 139     while (token != 0L){
 140       switch (token & (VF_OL_INSTR_LINE|VF_OL_INSTR_ARC|VF_OL_INSTR_BEZ)){
 141       case VF_OL_INSTR_LINE:
 142         token = read_xy(x, y, &olp, token);
 143         func_table[f](x[0], y[0], x[1], y[1]);
 144         break;
 145       case VF_OL_INSTR_ARC:
 146         token = read_xy(x, y, &olp, token);
 147         draw_arc(x, y, func_table[f]);
 148         break;
 149       case VF_OL_INSTR_BEZ:
 150         token = read_xy(x, y, &olp, token);
 151         draw_bezier(x, y, func_table[f]);
 152         break;
 153       default:
 154         fprintf(stderr, "VFlib: bogus outline data\n");
 155         vf_error = VF_ERR_BOGUS_OUTLINE;
 156         return -1;
 157       }
 158     }
 159   }
 160   return 0;
 161 }
 162 
 163 Private VF_OUTLINE_ELEM
 164 read_xy(int *x, int *y, VF_OUTLINE_ELEM **vfpp, VF_OUTLINE_ELEM token)
     /* [<][>][^][v][top][bottom][index][help] */
 165 {
 166   static int      xbeg, ybeg;
 167 
 168   if (((token & VF_OL_INSTR_TOKEN) != 0)
 169       && ((token & (VF_OL_INSTR_CWCURV|VF_OL_INSTR_CCWCURV)) != 0)){
 170     xbeg = VF_OL_GET_X(**vfpp) - VF_OL_COORD_OFFSET;
 171     ybeg = VF_OL_GET_Y(**vfpp) - VF_OL_COORD_OFFSET;
 172     token &= ~(VF_OL_INSTR_CWCURV|VF_OL_INSTR_CCWCURV);
 173   }
 174 
 175   switch (token & (VF_OL_INSTR_LINE|VF_OL_INSTR_ARC|VF_OL_INSTR_BEZ)){
 176   case VF_OL_INSTR_BEZ:
 177     *x++ = VF_OL_GET_X(**vfpp) - VF_OL_COORD_OFFSET;
 178     *y++ = VF_OL_GET_Y(**vfpp) - VF_OL_COORD_OFFSET;
 179     (*vfpp)++;
 180   case VF_OL_INSTR_ARC:
 181     *x++ = VF_OL_GET_X(**vfpp) - VF_OL_COORD_OFFSET;
 182     *y++ = VF_OL_GET_Y(**vfpp) - VF_OL_COORD_OFFSET;
 183     (*vfpp)++;
 184   case VF_OL_INSTR_LINE:
 185     *x++ = VF_OL_GET_X(**vfpp) - VF_OL_COORD_OFFSET;
 186     *y++ = VF_OL_GET_Y(**vfpp) - VF_OL_COORD_OFFSET;
 187     (*vfpp)++;
 188     break;
 189   default:
 190     fprintf(stderr, "VFlib: bogus outline data.\n");
 191     exit(1);
 192   }
 193   if ((**vfpp == 0) || (**vfpp & VF_OL_INSTR_TOKEN) != 0){
 194     token = **vfpp;
 195     (*vfpp)++;
 196     if (   (token == 0) 
 197         || ((token & (VF_OL_INSTR_CWCURV|VF_OL_INSTR_CCWCURV)) != 0) ){
 198       *x = xbeg;
 199       *y = ybeg;
 200       return token;
 201     } else {
 202       ;  /* ??? */
 203     }
 204   }
 205   *x = VF_OL_GET_X(**vfpp) - VF_OL_COORD_OFFSET;
 206   *y = VF_OL_GET_Y(**vfpp) - VF_OL_COORD_OFFSET;
 207   return token;
 208 }
 209 
 210 Private void 
 211 draw_arc(int *x, int *y, void (*draw_func)())
     /* [<][>][^][v][top][bottom][index][help] */
 212 {
 213   double   dx1, dy1, dx3, dy3, cx, cy, z, r, ang, dang, ang_step;
 214   int      i;
 215 
 216   dx1 = x[0] - x[1];
 217   dy1 = y[0] - y[1];
 218   dx3 = x[2] - x[1];
 219   dy3 = y[2] - y[1];
 220   
 221   z = dx1*dy3 - dx3*dy1;
 222   if (z == 0){
 223     if((dx1 == dx3) && (dy1 == dy3)){
 224       cx = dx1 / 2.0;
 225       cy = dy1 / 2.0;
 226       r = sqrt(cx*cx + cy*cy);
 227       cx += x[1];  cy += y[1];
 228       ang = 0.0;
 229       dang = 2.0 * M_PI;
 230     } else {
 231       (*draw_func)(x[0], y[0], x[2], y[2]);
 232       return;
 233     }
 234   } else {
 235     cx = ((dx1*dx1 + dy1*dy1)*dy3 - (dx3*dx3 + dy3*dy3)*dy1) / z / 2.0;
 236     cy = - ((dx1*dx1 + dy1*dy1)*dx3 - (dx3*dx3 + dy3*dy3)*dx1) / z / 2.0;
 237     r = sqrt(cx*cx + cy*cy);
 238     ang = atan2(dy1-cy, dx1-cx);
 239     dang = atan2(dy3-cy, dx3-cx);
 240     if (z < 0){
 241       if (dang < ang) 
 242         dang += 2.0 * M_PI;
 243     } else {
 244       if (dang > ang) 
 245         dang -= 2.0 * M_PI;
 246     }
 247     dang -= ang;
 248     if(dang == 0.0){
 249       ang = 0.0;  
 250       dang = 2.0 * M_PI;
 251     }
 252     cx += x[1];  
 253     cy += y[1];
 254   }
 255   ang_step = dang / (double)ARC_DIV;
 256   dx1 = x[0];
 257   dy1 = y[0];
 258   ang += ang_step;
 259   for (i = 1; i < ARC_DIV; i++){
 260     dx3 = cx + r * cos(ang);
 261     dy3 = cy + r * sin(ang);
 262     (*draw_func)((int)dx1, (int)dy1, (int)dx3, (int)dy3);
 263     dx1 = dx3;
 264     dy1 = dy3;
 265     ang += ang_step;
 266   }
 267   dx3 = x[2];
 268   dy3 = y[2];
 269   (*draw_func)((int)dx1, (int)dy1, (int)dx3, (int)dy3);
 270 }
 271 
 272 Private void
 273 draw_bezier(int *x, int* y, void (*draw_func)())
     /* [<][>][^][v][top][bottom][index][help] */
 274 {
 275   int            i, xs, ys, xe, ye;
 276   static double  b[BEZ_DIV][4];
 277   static double  t = -1;
 278 
 279   if (t < 0){
 280     for (i = 0; i < BEZ_DIV; i++){
 281       t = (double)(i+1) / BEZ_DIV;
 282       b[i][0] = (1.0-t)*(1.0-t)*(1.0-t);
 283       b[i][1] = 3.0*t*(1.0-t)*(1.0-t);
 284       b[i][2] = 3.0*t*t*(1.0-t);
 285       b[i][3] = t*t*t;
 286     }
 287   }
 288   xs = x[0];
 289   ys = y[0];
 290   for (i = 0; i < BEZ_DIV; i++) {
 291     xe = b[i][0]*x[0] + b[i][1]*x[1] + b[i][2]*x[2] + b[i][3]*x[3];
 292     ye = b[i][0]*y[0] + b[i][1]*y[1] + b[i][2]*y[2] + b[i][3]*y[3];
 293     (*draw_func)((int)xs, (int)ys, (int)xe, (int)ye);
 294     xs = xe;
 295     ys = ye;
 296   }
 297 }
 298 
 299 Private void 
 300 trace_outline(int x1, int y1, int x2, int y2)
     /* [<][>][^][v][top][bottom][index][help] */
 301 {
 302   int     xx1, yy1, xx2, yy2;
 303   int     dxx, dyy, dxx2, dyy2, e, i, tmp;
 304   unsigned char        *bm_ptr, mask;
 305   
 306   xx1 = toint(((double)x1*Vbm->bbx_width)  / (double)Vmax_width);
 307   yy1 = toint(((double)y1*Vbm->bbx_height) / (double)Vmax_height);
 308   xx2 = toint(((double)x2*Vbm->bbx_width)  / (double)Vmax_width);
 309   yy2 = toint(((double)y2*Vbm->bbx_height) / (double)Vmax_height);
 310   if (xx1 < 0) xx1 = 0; 
 311   else if (xx1 >= Vbm->bbx_width)  xx1 = Vbm->bbx_width-1;
 312   if (yy1 < 0) yy1 = 0;
 313   else if (yy1 >= Vbm->bbx_height) yy1 = Vbm->bbx_height-1;
 314   if (xx2 < 0) xx2 = 0;
 315   else if (xx2 >= Vbm->bbx_width)  xx2 = Vbm->bbx_width-1;
 316   if (yy2 < 0) yy2 = 0; 
 317   else if (yy2 >= Vbm->bbx_height) yy2 = Vbm->bbx_height-1;
 318 #if 0
 319   printf("LINE: (%d,%d)-(%d,%d)\n", xx1, yy1, xx2, yy2);
 320 #endif
 321 
 322   if ((dyy = yy2 - yy1) < 0){
 323     tmp = xx1; xx1 = xx2; xx2 = tmp;
 324     tmp = yy1; yy1 = yy2; yy2 = tmp;
 325     dyy = -dyy;
 326   }
 327   dxx = xx2 - xx1;
 328   if ((dxx == 0) && (dyy == 0)){
 329     Vbm->bitmap[yy1*Vbm->raster + (xx1/0x08)] |= bit_table[xx1%0x08];
 330     return;
 331   }
 332   if (dxx < 0) 
 333     dxx = -dxx;
 334 
 335   bm_ptr = &Vbm->bitmap[yy1*Vbm->raster + (xx1/0x08)];
 336   mask = bit_table[xx1%0x08];
 337   dxx2 = 2*dxx;
 338   dyy2 = 2*dyy;
 339   if (dxx < dyy){
 340     e = dxx2 - dyy;
 341     if (xx1 < xx2){
 342       for (i = 0; i <= dyy; i++){
 343         *bm_ptr |= mask;
 344         while (e >= 0){
 345           if ((mask >>= 1) == 0){
 346             bm_ptr++;
 347             mask = 0x80;
 348           }
 349           e -= dyy2;
 350         }
 351         bm_ptr += Vbm->raster;
 352         e += dxx2;
 353       }
 354     } else {
 355       for (i = 0; i <= dyy; i++) {
 356         *bm_ptr |= mask;
 357         while (e >= 0) {
 358           if ((mask <<= 1) == 0) {
 359             bm_ptr--;
 360             mask = 0x1;
 361           }
 362           e -= dyy2;
 363         }
 364         bm_ptr += Vbm->raster;
 365         e += dxx2;
 366       }
 367     }
 368   } else {
 369     e = dyy2 - dxx;
 370     if (xx1 < xx2){
 371       for (i = 0; i <= dxx; i++){
 372         *bm_ptr |= mask;
 373         while (e >= 0) {
 374           bm_ptr += Vbm->raster;
 375           e -= dxx2;
 376         }
 377         if ((mask >>= 1) == 0) {
 378           bm_ptr++;
 379           mask = 0x80;
 380         }
 381         e += dyy2;
 382       }
 383     } else {
 384       for (i = 0; i <= dxx; i++){
 385         *bm_ptr |= mask;
 386         while (e >= 0) {
 387           bm_ptr += Vbm->raster;
 388           e -= dxx2;
 389         }
 390         if ((mask <<= 1) == 0){
 391           bm_ptr--;
 392           mask = 0x1;
 393         }
 394         e += dyy2;
 395       }
 396     }
 397   }
 398 }
 399 
 400 Private void 
 401 fill_edges(int x1, int y1, int x2, int y2)
     /* [<][>][^][v][top][bottom][index][help] */
 402 {
 403   int      xx1, yy1, xx2, yy2;
 404   int      dxx, dyy, dxx2, dyy2, sx, e, i, j, tmp;
 405   unsigned char *bm_ptr;
 406   int      bit, rbytes;
 407   
 408   xx1 = toint(((double)x1*Vbm->bbx_width)  / (double)Vmax_width);
 409   yy1 = toint(((double)y1*Vbm->bbx_height) / (double)Vmax_height);
 410   xx2 = toint(((double)x2*Vbm->bbx_width)  / (double)Vmax_width);
 411   yy2 = toint(((double)y2*Vbm->bbx_height) / (double)Vmax_height);
 412   if (xx1 < 0) xx1 = 0; 
 413   else if (xx1 >= Vbm->bbx_width)  xx1 = Vbm->bbx_width-1;
 414   if (yy1 < 0) yy1 = 0;
 415   else if (yy1 >= Vbm->bbx_height) yy1 = Vbm->bbx_height-1;
 416   if (xx2 < 0) xx2 = 0;
 417   else if (xx2 >= Vbm->bbx_width)  xx2 = Vbm->bbx_width-1;
 418   if (yy2 < 0) yy2 = 0; 
 419   else if (yy2 >= Vbm->bbx_height) yy2 = Vbm->bbx_height-1;
 420 
 421 #if 0
 422   printf("LINE: (%d,%d)-(%d,%d)\n", xx1, yy1, xx2, yy2);
 423 #endif
 424 
 425   if ((dyy = yy2-yy1) == 0) 
 426     return;
 427   if (dyy < 0){
 428     tmp = xx1; xx1 = xx2; xx2 = tmp;
 429     tmp = yy1; yy1 = yy2; yy2 = tmp;
 430     dyy = -dyy;
 431   }
 432   dxx = xx2 - xx1;
 433   sx = (dxx > 0) ? 1 : -1;
 434   if (dxx < 0) 
 435     dxx = -dxx;
 436 
 437   rbytes = Vbm->raster - (xx1/8) + 1;
 438   bit = xx1 % 8;
 439   dxx2 = 2*dxx;
 440   dyy2 = 2*dyy;
 441   e = dxx2-dyy;
 442 
 443   bm_ptr = &Vbm->bitmap[yy1*Vbm->raster + (xx1/8)];
 444   if ((xx1 == xx2) && (yy1 == yy2)){
 445     /* *bm_ptr |= bit_table[xx1%0x08];*/
 446     return;
 447   }
 448 
 449   for (i = 0; i < dyy; i++){
 450     bm_ptr[0] ^= flip[bit];
 451     for (j = 1; j <= rbytes; j++)
 452       bm_ptr[j] = ~bm_ptr[j];
 453     while (e >= 0){
 454       bit += sx;
 455       if (bit & 8){
 456         bm_ptr += sx;
 457         rbytes -= sx;
 458         bit &= 7;
 459       }
 460       e -= dyy2;
 461     }
 462     bm_ptr += Vbm->raster;
 463     e += dxx2;
 464   }
 465 }
 466 
 467 
 468 /*EOF*/

/* [<][>][^][v][top][bottom][index][help] */