src/raster.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- VF_OutlineToBitmap
- vf_outline_to_bitmap
- vf_draw_outline
- read_xy
- draw_arc
- draw_bezier
- trace_outline
- 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*/