1 /*
2 * We are going to take a file format and convert the content into a bitmap
3 * array based on basic (bristol) vector graphics. The main goal is to render
4 * silkscreen bitmaps for fonts, the overlays for the synths.
5 *
6 * The graphics will be referenced on 1000 by 1000 arrays? No, the format
7 * should include it's rough layout. We should have a subformat for fonts so
8 * we can call 'font/size' for example. We need a 'fill' option for boxes, a
9 * line option, each should include a color.
10 *
11 * Type: line, linearray, fill, <sub>
12 * color: 0xAARRGGBB
13 * coord: x/y
14 */
15 #include <stdio.h>
16 #include <math.h>
17 #include <brightoninternals.h>
18
19 #include <font1.h>
20
21 #ifndef ANDROID_COLORS
22 static brightonWindow *bwin;
23 #endif
24
25 /*
26 * We have the bitmap, we are given an area on that bitmap, we now render the
27 * fill into that area.
28 */
29 static void
bvgRenderFill(brightonBitmap * bm,bvgImage * image,int stage,int ox,int oy,int ow,int oh)30 bvgRenderFill(brightonBitmap *bm, bvgImage *image, int stage,
31 int ox, int oy, int ow, int oh)
32 {
33 float sx, sy, ex, ey;
34 float x, y;
35 int c = image->element[stage].line.color;
36
37 #ifndef ANDROID_COLORS
38 c = brightonGetGC(bwin,
39 (c>>8) & 0x0000ff00,
40 c & 0x0000ff00,
41 (c << 8) & 0x0000ff00);
42 #endif
43
44 /*
45 * Starting X point: origin-x + stage-x * stage-w / bitmap-w
46 */
47 if ((sx = ox + image->element[stage].line.x * ow / image->width)
48 >= bm->width)
49 return;
50
51 /*
52 * Starting Y point: origin-y + stage-y * stage-h / bitmap-h
53 */
54 if ((sy = oy + image->element[stage].line.y * oh / image->height)
55 >= bm->height)
56 return;
57
58 /*
59 * Ending X point: origin-x + stage-x * stage-w / bitmap-w
60 */
61 if ((ex = ox + image->element[stage].line.X * ow / image->width)
62 >= bm->width)
63 return;
64
65 /*
66 * Ending Y point: origin-y + stage-y * stage-h / bitmap-h
67 */
68 if ((ey = oy + image->element[stage].line.Y * oh / image->height)
69 >= bm->height)
70 return;
71
72 // Normalise
73 if (sx > ex)
74 {
75 float tx = ex;
76 ex = sx;
77 sx = tx;
78 }
79 // Normalise
80 if (sy > ey)
81 {
82 float ty = ey;
83 ey = sy;
84 sy = ty;
85 }
86
87 for (x = sx; x <= ex; x += 1)
88 {
89 for (y = sy; y <= ey; y += 1)
90 {
91 if ((x < 0) || (y < 0) || (x >= bm->width) || (y >= bm->height))
92 break;
93 // Set pixel x, y
94 //printf("set %i %i\n", (int) x, (int) y);
95 bm->pixels[(int) (round(x) + ((int) y) * bm->width)] = c;
96 }
97 }
98 }
99
100 static void
bvgSetPoint(brightonBitmap * bm,int style,int x,int y,int c)101 bvgSetPoint(brightonBitmap *bm, int style, int x, int y, int c)
102 {
103 int nx, ny;
104
105 for (nx = 0; nx < style; nx++)
106 for (ny = 0; ny < style; ny++)
107 bm->pixels[nx + x + (ny + y) * bm->width] = c;
108 }
109
110 /*
111 * We have the bitmap, we are given an area on that bitmap, we now render the
112 * line into that area.
113 */
114 static int
bvgRenderVector(brightonBitmap * bm,bvgImage * image,bvgVect * v,int c,int style,int ox,int oy,int ow,int oh)115 bvgRenderVector(brightonBitmap *bm, bvgImage *image, bvgVect *v, int c,
116 int style, int ox, int oy, int ow, int oh)
117 {
118 float sx, sy, ex, ey;
119 float dx, dy;
120 float x, y;
121 int i, startx, starty, w = 0;
122
123 if (style <= 0)
124 style = 1;
125
126 if (v->count < 2)
127 return(0);
128
129 #ifndef ANDROID_COLORS
130 c = brightonGetGC(bwin,
131 (c>>8) & 0x0000ff00,
132 c & 0x0000ff00,
133 (c << 8) & 0x0000ff00);
134 #endif
135
136 /*
137 * Starting X point: origin-x + stage-x * stage-w / bitmap-w
138 if ((sx = ox + v->coords[0].x * ow / image->width)
139 */
140 if ((sx = ox * bm->width / image->width) >= bm->width)
141 return(0);
142
143 /*
144 * Starting Y point: origin-y + stage-y * stage-h / bitmap-h
145 if ((sy = oy + v->coords[0].y * oh / image->height)
146 */
147 if ((sy = oy * bm->height / image->height) >= bm->height)
148 return(0);
149
150 startx = sx;
151 starty = sy;
152
153 if ((sx = startx + ow * v->coords[0].x * bm->width / (image->width * 100))
154 >= bm->width)
155 return(0);
156 if ((sy = starty + oh * v->coords[0].y * bm->height / (image->height * 100))
157 >= bm->height)
158 return(0);
159
160 for (i = 1; i < v->count; i++)
161 {
162 if (v->coords[i].x < 0)
163 {
164 if (++i >= v->count)
165 return(0);
166
167 if ((sx = startx + ow * v->coords[i].x * bm->width / (image->width * 100))
168 >= bm->width)
169 return(0);
170 if ((sy = starty + oh * v->coords[i].y * bm->height / (image->height * 100))
171 >= bm->height)
172 return(0);
173
174 continue;
175 }
176
177 /*
178 * Ending X point: origin-x + stage-x * stage-w / bitmap-w
179 */
180 if ((ex = startx + ow * v->coords[i].x * bm->width / (image->width * 100))
181 >= bm->width)
182 return(w - startx);
183
184 /*
185 * Ending Y point: origin-y + stage-y * stage-h / bitmap-h
186 */
187 if ((ey = starty + oh * v->coords[i].y * bm->height / (image->height * 100))
188 >= bm->height)
189 return(w - startx);
190
191 if (ex > w) w = ex;
192
193 /*
194 * There are 8 cases we need to check for with 4 net actions
195 */
196 if ((sx <= ex) && (sy <= ey) && ((ex - sx) >= (ey - sy)))
197 {
198 dy = ((float) (ey - sy)) / (ex - sx);
199 y = sy;
200
201 for (x = sx; x <= ex; x += 1)
202 {
203 if ((x < 0) || (y < 0) || (x >= bm->width) || (y >= bm->height))
204 break;
205
206 bvgSetPoint(bm, style, round(x), round(y), c);
207 y += dy;
208 }
209 } else if ((sx <= ex) && (sy > ey) && ((ex - sx) >= (sy - ey))) {
210 dy = ((float) (ey - sy)) / (ex - sx);
211 y = sy;
212
213 for (x = sx; x <= ex; x += 1)
214 {
215 if ((x < 0) || (y < 0) || (x >= bm->width) || (y >= bm->height))
216 break;
217
218 bvgSetPoint(bm, style, round(x), round(y), c);
219 y += dy;
220 }
221 } else if ((sx >= ex) && (sy <= ey) && ((sx - ex) >= (ey - sy))) {
222 dy = ((float) (sy - ey)) / (ex - sx);
223 y = sy;
224
225 for (x = sx; x >= ex; x -= 1)
226 {
227 if ((x < 0) || (y < 0) || (x >= bm->width) || (y >= bm->height))
228 break;
229
230 bvgSetPoint(bm, style, round(x), round(y), c);
231 y += dy;
232 }
233 } else if ((sx >= ex) && (sy >= ey) && ((sx - ex) >= (sy - ey))) {
234 dy = ((float) (sy - ey)) / (ex - sx);
235 y = sy;
236
237 for (x = sx; x >= ex; x -= 1)
238 {
239 if ((x < 0) || (y < 0) || (x >= bm->width) || (y >= bm->height))
240 break;
241
242 bvgSetPoint(bm, style, round(x), round(y), c);
243 y += dy;
244 }
245 } else if ((sx <= ex) && (sy <= ey) && ((ex - sx) <= (ey - sy))) {
246 dx = ((float) (ex - sx)) / (ey - sy);
247 x = sx;
248
249 for (y = sy; y <= ey; y += 1)
250 {
251 if ((x < 0) || (y < 0) || (x >= bm->width) || (y >= bm->height))
252 break;
253
254 bvgSetPoint(bm, style, round(x), round(y), c);
255 x += dx;
256 }
257 } else if ((sx >= ex) && (sy <= ey) && ((sx - ex) <= (ey - sy))) {
258 dx = ((float) (ex - sx)) / (ey - sy);
259 x = sx;
260
261 for (y = sy; y <= ey; y += 1)
262 {
263 if ((x < 0) || (y < 0) || (x >= bm->width) || (y >= bm->height))
264 break;
265
266 bvgSetPoint(bm, style, round(x), round(y), c);
267 x += dx;
268 }
269 } else if ((sx <= ex) && (sy > ey) && ((ex - sx) >= (sy - ey))) {
270 dx = ((float) (sx - ex)) / (ey - sy);
271 x = sx;
272
273 for (y = sy; y >= ey; y -= 1)
274 {
275 if ((x < 0) || (y < 0) || (x >= bm->width) || (y >= bm->height))
276 break;
277
278 bvgSetPoint(bm, style, round(x), round(y), c);
279 x += dx;
280 }
281 } else {
282 dx = ((float) (sx - ex)) / (ey - sy);
283 x = sx;
284
285 for (y = sy; y >= ey; y -= 1)
286 {
287 if ((x < 0) || (y < 0) || (x >= bm->width) || (y >= bm->height))
288 break;
289
290 bvgSetPoint(bm, style, round(x), round(y), c);
291 x += dx;
292 }
293 }
294
295 sx = ex;
296 sy = ey;
297 }
298 return(w - startx);
299 }
300
301 /*
302 * We have the bitmap, we are given an area on that bitmap, we now render the
303 * line into that area.
304 */
305 static void
bvgRenderLine(brightonBitmap * bm,bvgImage * image,int stage,int ox,int oy,int ow,int oh)306 bvgRenderLine(brightonBitmap *bm, bvgImage *image, int stage,
307 int ox, int oy, int ow, int oh)
308 {
309 float sx, sy, ex, ey;
310 float dx, dy;
311 float x, y;
312 int c = image->element[stage].line.color;
313 int style = image->element[stage].line.type & BVG_STYLE_MASK;
314
315 if (style <= 0)
316 style = 1;
317
318 #ifndef ANDROID_COLORS
319 c = brightonGetGC(bwin,
320 (c>>8) & 0x0000ff00,
321 c & 0x0000ff00,
322 (c << 8) & 0x0000ff00);
323 #endif
324
325 /*
326 * Starting X point: origin-x + stage-x * stage-w / bitmap-w
327 */
328 if ((sx = ox + image->element[stage].line.x * ow / image->width)
329 >= bm->width)
330 return;
331
332 /*
333 * Starting Y point: origin-y + stage-y * stage-h / bitmap-h
334 */
335 if ((sy = oy + image->element[stage].line.y * oh / image->height)
336 >= bm->height)
337 return;
338
339 /*
340 * Ending X point: origin-x + stage-x * stage-w / bitmap-w
341 */
342 if ((ex = ox + image->element[stage].line.X * ow / image->width)
343 >= bm->width)
344 return;
345
346 /*
347 * Ending Y point: origin-y + stage-y * stage-h / bitmap-h
348 */
349 if ((ey = oy + image->element[stage].line.Y * oh / image->height)
350 >= bm->height)
351 return;
352
353 /*
354 * There are 8 cases we need to check for with 4 net actions
355 */
356 if ((sx <= ex) && (sy <= ey) && ((ex - sx) >= (ey - sy)))
357 {
358 dy = ((float) (ey - sy)) / (ex - sx);
359 y = sy;
360
361 for (x = sx; x <= ex; x += 1)
362 {
363 if ((x < 0) || (y < 0) || (x >= bm->width) || (y >= bm->height))
364 break;
365
366 bvgSetPoint(bm, style, round(x), round(y), c);
367 y += dy;
368 }
369 } else if ((sx <= ex) && (sy > ey) && ((ex - sx) >= (sy - ey))) {
370 dy = ((float) (ey - sy)) / (ex - sx);
371 y = sy;
372
373 for (x = sx; x <= ex; x += 1)
374 {
375 if ((x < 0) || (y < 0) || (x >= bm->width) || (y >= bm->height))
376 break;
377
378 bvgSetPoint(bm, style, round(x), round(y), c);
379 y += dy;
380 }
381 } else if ((sx >= ex) && (sy <= ey) && ((sx - ex) >= (ey - sy))) {
382 dy = ((float) (sy - ey)) / (ex - sx);
383 y = sy;
384
385 for (x = sx; x >= ex; x -= 1)
386 {
387 if ((x < 0) || (y < 0) || (x >= bm->width) || (y >= bm->height))
388 break;
389
390 bvgSetPoint(bm, style, round(x), round(y), c);
391 y += dy;
392 }
393 } else if ((sx >= ex) && (sy >= ey) && ((sx - ex) >= (sy - ey))) {
394 dy = ((float) (sy - ey)) / (ex - sx);
395 y = sy;
396
397 for (x = sx; x >= ex; x -= 1)
398 {
399 if ((x < 0) || (y < 0) || (x >= bm->width) || (y >= bm->height))
400 break;
401
402 bvgSetPoint(bm, style, round(x), round(y), c);
403 y += dy;
404 }
405 } else if ((sx <= ex) && (sy <= ey) && ((ex - sx) <= (ey - sy))) {
406 dx = ((float) (ex - sx)) / (ey - sy);
407 x = sx;
408
409 for (y = sy; y <= ey; y += 1)
410 {
411 if ((x < 0) || (y < 0) || (x >= bm->width) || (y >= bm->height))
412 break;
413
414 bvgSetPoint(bm, style, round(x), round(y), c);
415 x += dx;
416 }
417 } else if ((sx >= ex) && (sy <= ey) && ((sx - ex) <= (ey - sy))) {
418 dx = ((float) (ex - sx)) / (ey - sy);
419 x = sx;
420
421 for (y = sy; y <= ey; y += 1)
422 {
423 if ((x < 0) || (y < 0) || (x >= bm->width) || (y >= bm->height))
424 break;
425
426 bvgSetPoint(bm, style, round(x), round(y), c);
427 x += dx;
428 }
429 } else if ((sx <= ex) && (sy > ey) && ((ex - sx) >= (sy - ey))) {
430 dx = ((float) (sx - ex)) / (ey - sy);
431 x = sx;
432
433 for (y = sy; y >= ey; y -= 1)
434 {
435 if ((x < 0) || (y < 0) || (x >= bm->width) || (y >= bm->height))
436 break;
437
438 bvgSetPoint(bm, style, round(x), round(y), c);
439 x += dx;
440 }
441 } else {
442 dx = ((float) (sx - ex)) / (ey - sy);
443 x = sx;
444
445 for (y = sy; y >= ey; y -= 1)
446 {
447 if ((x < 0) || (y < 0) || (x >= bm->width) || (y >= bm->height))
448 break;
449
450 bvgSetPoint(bm, style, round(x), round(y), c);
451 x += dx;
452 }
453 }
454 }
455
456 static void
bvgRenderString(brightonBitmap * bm,bvgImage * image,int stage,int ox,int oy,int ow,int oh)457 bvgRenderString(brightonBitmap *bm, bvgImage *image, int stage,
458 int ox, int oy, int ow, int oh)
459 {
460 int i = 0, step, len;
461
462 len = strlen(image->element[stage].string.string);
463 step = ow / len - 1;
464 ow = step - 1;
465
466 while (image->element[stage].string.string[i] != '\0')
467 {
468 if (image->element[stage].string.string[i] != ' ')
469 bvgRenderVector(bm, image,
470 font1[(int) image->element[stage].string.string[i]],
471 image->element[stage].line.color,
472 image->element[stage].line.type & BVG_STYLE_MASK,
473 ox, oy, ow, oh);
474
475 ox += step;
476
477 i++;
478 }
479 }
480
481 extern iMap imageMap[];
482
483 bvgImage *
findImage(char * name)484 findImage(char *name)
485 {
486 int i = 0;
487
488 if (name == NULL)
489 return(NULL);
490
491 while (imageMap[i].image != NULL)
492 {
493 if (strcmp(name, imageMap[i].name) == 0)
494 return(imageMap[i].image);
495 i++;
496 }
497
498 return NULL;
499 }
500
501 static void
bvgMacro(brightonBitmap * bm,bvgImage * image,int x,int y,int w,int h)502 bvgMacro(brightonBitmap *bm, bvgImage *image, int x, int y, int w, int h)
503 {
504 int stage;
505
506 if (image == NULL)
507 return;
508
509 for (stage = 0; stage < image->count; stage++)
510 {
511 switch (image->element[stage].line.type & BVG_TYPE_MASK) {
512 case BVG_LINE:
513 bvgRenderLine(bm, image, stage, x, y, w, h);
514 break;
515 case BVG_SQUARE:
516 bvgRenderFill(bm, image, stage, x, y, w, h);
517 break;
518 case BVG_STRING:
519 bvgRenderString(bm, image, stage,
520 x + image->element[stage].string.x * w / 100,
521 y + image->element[stage].string.y * h / 100,
522 image->element[stage].string.W * w / 100,
523 image->element[stage].string.H * h / 100);
524 break;
525 case BVG_VECT:
526 bvgRenderVector(bm, image,
527 image->element[stage].vector.vector,
528 image->element[stage].line.color,
529 image->element[stage].line.type & BVG_STYLE_MASK,
530 x + image->element[stage].vector.x * w / 100,
531 y + image->element[stage].vector.y * h / 100,
532 image->element[stage].vector.W * w / 100,
533 image->element[stage].vector.H * h / 100);
534 break;
535 }
536 }
537 }
538
539 int
bvgRender(brightonBitmap * bm,bvgImage * image,int x,int y,int w,int h)540 bvgRender(brightonBitmap *bm, bvgImage *image, int x, int y, int w, int h)
541 {
542 int stage;
543
544 if (image == NULL)
545 return(0);
546
547 if (image->color != 0)
548 memset(bm->pixels, 0, bm->width * bm->height * sizeof(int));
549
550 for (stage = 0; stage < image->count; stage++)
551 {
552 switch (image->element[stage].line.type & BVG_TYPE_MASK) {
553 case BVG_LINE:
554 bvgRenderLine(bm, image, stage, x, y, w, h);
555 break;
556 case BVG_SQUARE:
557 bvgRenderFill(bm, image, stage, x, y, w, h);
558 break;
559 case BVG_STRING:
560 bvgRenderString(bm, image, stage,
561 image->element[stage].string.x,
562 image->element[stage].string.y,
563 image->element[stage].string.W,
564 image->element[stage].string.H);
565 break;
566 case BVG_IMAGE:
567 // This is recursion, take care with subimage coords
568 bvgMacro(bm,
569 image->element[stage].image.image,
570 image->element[stage].image.x,
571 image->element[stage].image.y,
572 image->element[stage].image.w,
573 image->element[stage].image.h);
574 break;
575 case BVG_VECT:
576 bvgRenderVector(bm, image,
577 image->element[stage].vector.vector,
578 image->element[stage].line.color,
579 image->element[stage].line.type & BVG_STYLE_MASK,
580 image->element[stage].vector.x,
581 image->element[stage].vector.y,
582 image->element[stage].vector.W,
583 image->element[stage].vector.H);
584 break;
585 }
586 }
587
588 return(0);
589 }
590
591 void
bvgRenderInit(brightonWindow * bw)592 bvgRenderInit(brightonWindow *bw)
593 {
594 #ifndef ANDROID_COLORS
595 bwin = bw;
596 #endif
597
598 initFont1();
599 }
600
601 void
bvgRenderInt(brightonWindow * bw,char * name,brightonBitmap * bm)602 bvgRenderInt(brightonWindow *bw, char *name, brightonBitmap *bm)
603 {
604 if ((bm == NULL) || (bm->pixels == NULL))
605 return;
606
607 if (font1[0] == NULL)
608 bvgRenderInit(bw);
609
610 bvgRender(bm, findImage(name), 0, 0, bm->width, bm->height);
611 }
612
613 #ifdef TESTING
main()614 main()
615 {
616 brightonBitmap bm;
617
618 bm.width = 788;
619 bm.height = 244;
620 bm.pixels = malloc(bm.width * bm.height * sizeof(int));
621
622 bvgRender(&bm, &JunoImage, 0, 0, 788, 244);
623 return(0);
624 }
625 #endif
626