Bug Summary

File:generic.c
Warning:line 192, column 24
Division by zero

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name generic.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/var/lib/jenkins/workspace/scan-build-libnsfb -resource-dir /usr/lib/llvm-14/lib/clang/14.0.6 -D _BSD_SOURCE -D _DEFAULT_SOURCE -D _POSIX_C_SOURCE=200112L -I /var/lib/jenkins/workspace/scan-build-libnsfb/include/ -I /var/lib/jenkins/workspace/scan-build-libnsfb/src -D _ALIGNED=__attribute__((aligned)) -D STMTEXPR=1 -D DEBUG -internal-isystem /usr/lib/llvm-14/lib/clang/14.0.6/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Og -Wwrite-strings -Wno-error -std=c99 -fconst-strings -fdebug-compilation-dir=/var/lib/jenkins/workspace/scan-build-libnsfb -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-display-progress -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /var/lib/jenkins/workspace/scan-build-libnsfb/clangScanBuildReports/2024-12-10-112917-2311854-1 -x c src/plot/generic.c
1/*
2 * Copyright 2009 Vincent Sanders <vince@simtec.co.uk>
3 * Copyright 2009 Michael Drake <tlsa@netsurf-browser.org>
4 *
5 * This file is part of libnsfb, http://www.netsurf-browser.org/
6 * Licenced under the MIT License,
7 * http://www.opensource.org/licenses/mit-license.php
8 */
9
10/** \file
11 * generic plotter functions which are not depth dependant (implementation).
12 */
13
14#include <stdbool.h>
15#include <limits.h>
16#include <stdlib.h>
17#include <string.h>
18
19#include "libnsfb.h"
20#include "libnsfb_plot.h"
21#include "libnsfb_plot_util.h"
22
23#include "nsfb.h"
24#include "plot.h"
25#include "surface.h"
26
27extern const nsfb_plotter_fns_t _nsfb_1bpp_plotters;
28extern const nsfb_plotter_fns_t _nsfb_8bpp_plotters;
29extern const nsfb_plotter_fns_t _nsfb_16bpp_plotters;
30extern const nsfb_plotter_fns_t _nsfb_24bpp_plotters;
31extern const nsfb_plotter_fns_t _nsfb_32bpp_xrgb8888_plotters;
32extern const nsfb_plotter_fns_t _nsfb_32bpp_xbgr8888_plotters;
33
34static bool_Bool set_clip(nsfb_t *nsfb, nsfb_bbox_t *clip)
35{
36 nsfb_bbox_t fbarea;
37
38 /* screen area */
39 fbarea.x0 = 0;
40 fbarea.y0 = 0;
41 fbarea.x1 = nsfb->width;
42 fbarea.y1 = nsfb->height;
43
44 if (clip == NULL((void*)0)) {
45 nsfb->clip = fbarea;
46 } else {
47 if (!nsfb_plot_clip(&fbarea, clip))
48 return false0;
49
50 nsfb->clip = *clip;
51 }
52 return true1;
53}
54
55static bool_Bool get_clip(nsfb_t *nsfb, nsfb_bbox_t *clip)
56{
57 *clip = nsfb->clip;
58 return true1;
59}
60
61static bool_Bool clg(nsfb_t *nsfb, nsfb_colour_t c)
62{
63 return nsfb->plotter_fns->fill(nsfb, &nsfb->clip, c);
64}
65
66/**
67 * Establish whether there is any value in a line's crossing.
68 * (Helper function for find_span().)
69 *
70 * \param x x coordinate of intersection
71 * \param y current y level
72 * \param x0 line start coordinate
73 * \param y0 line start coordinate
74 * \param x1 line end coordinate
75 * \param y1 line end coordinate
76 * \return true if crossing has value
77 *
78 * + | | /
79 * / | |/
80 * y level -- ----/---- ----+---- ----+---- ----+----
81 * / / /|
82 * + / / |
83 *
84 * (a) (b) (c) (d)
85 *
86 *
87 * Figure (a) values: 1 = 1 -- Odd -- Valid crossing
88 * Figure (b) values: 0 + 1 = 1 -- Odd -- Valid crossing
89 * Figure (c) values: 1 + 1 = 2 -- Even -- Not valid crossing
90 * Figure (d) values: 0 + 0 = 0 -- Even -- Not valid crossing
91 *
92 * Vertices are shared between consecutive lines. This function ensures that
93 * the vertex point is only counted as a crossing for one of the lines by
94 * only considering crossings of the top vertex. This is what NetSurf's
95 * plotter API expects.
96 *
97 * It's up to the client to call this function for both lines and check the
98 * evenness of the total.
99 */
100static bool_Bool establish_crossing_value(int x, int y, int x0, int y0,
101 int x1, int y1)
102{
103 bool_Bool v1 = (x == x0 && y == y0); /* whether we're crossing 1st vertex */
104 bool_Bool v2 = (x == x1 && y == y1); /* whether we're crossing 2nd vertex */
105
106 if ((v1 && (y0 < y1)) || (v2 && (y1 < y0))) {
107 /* crossing top vertex */
108 return true1;
109 } else if (!v1 && !v2) {
110 /* Intersection with current y level is not at a vertex.
111 * Normal crossing. */
112 return true1;
113 }
114 return false0;
115}
116
117
118/**
119 * Find first filled span along horizontal line at given coordinate
120 *
121 * \param p array of polygon vertices (x1, y1, x2, y2, ... , xN, yN)
122 * \param n number of polygon vertex values (N * 2)
123 * \param x current position along current scan line
124 * \param y position of current scan line
125 * \param x0 updated to start of filled area
126 * \param x1 updated to end of filled area
127 * \return true if an intersection was found
128 */
129static bool_Bool find_span(const int *p, int n, int x, int y, int *x0, int *x1)
130{
131 enum {
132 NO_MIN = INT_MIN(-2147483647 -1) + 1,
133 NO_MAX = INT_MAX2147483647 - 1,
134 };
135 int i;
136 int p_x0, p_y0;
137 int p_x1, p_y1;
138 int x0_min, x1_min;
139 int x_new;
140 unsigned int x0c, x1c; /* counters for crossings at span end points */
141 bool_Bool crossing_value;
142 bool_Bool found_span_start = false0;
143
144 x0_min = x1_min = NO_MIN;
145 x0c = x1c = 0;
146
147 /* search row for next span, returning it if one exists */
148 do {
149 /* reset endpoint info, if valid span endpoints not found */
150 if (!found_span_start
36.1
'found_span_start' is false
) {
37
Taking true branch
151 *x0 = NO_MAX;
152 }
153 *x1 = NO_MAX;
154
155 /* search all lines in polygon */
156 for (i = 0; i
37.1
'i' is < 'n'
45.1
'i' is < 'n'
< n; i = i + 2) {
38
Loop condition is true. Entering loop body
46
Loop condition is true. Entering loop body
157 /* get line endpoints */
158 if (i != n - 2) {
39
Taking true branch
47
Assuming the condition is false
48
Taking false branch
159 /* not the last line */
160 p_x0 = p[i]; p_y0 = p[i + 1];
161 p_x1 = p[i + 2]; p_y1 = p[i + 3];
162 } else {
163 /* last line; 2nd endpoint is first vertex */
164 p_x0 = p[i]; p_y0 = p[i + 1];
165 p_x1 = p[0]; p_y1 = p[1];
166 }
167 /* ignore horizontal lines */
168 if (p_y0
39.1
'p_y0' is not equal to 'p_y1'
48.1
'p_y0' is not equal to 'p_y1'
== p_y1)
169 continue;
170
171 /* ignore lines that don't cross this y level */
172 if ((y
39.2
'y' is < 'p_y0'
48.2
'y' is >= 'p_y0'
< p_y0 && y
39.3
'y' is >= 'p_y1'
< p_y1) || (y
39.4
'y' is <= 'p_y0'
48.3
'y' is <= 'p_y0'
> p_y0 && y > p_y1))
173 continue;
174
175 if (p_x0
39.5
'p_x0' is not equal to 'p_x1'
48.4
'p_x0' is not equal to 'p_x1'
== p_x1) {
40
Taking false branch
49
Taking false branch
176 /* vertical line, x is constant */
177 x_new = p_x0;
178 } else {
179 /* find crossing (intersection of this line and
180 * current y level) */
181 int num = (y - p_y0) * (p_x1 - p_x0);
182 int den = (p_y1 - p_y0);
50
'den' initialized here
183
184 /* To round to nearest (rather than down)
185 * half the denominator is either added to
186 * or subtracted from the numerator,
187 * depending on whether the numerator and
188 * denominator have the same sign. */
189 num = ((num < 0) == (den < 0)) ?
41
Assuming 'num' is < 0
42
Assuming 'den' is >= 0
43
'?' condition is false
51
Assuming 'den' is >= 0
52
'?' condition is true
190 num + (den / 2) :
191 num - (den / 2);
192 x_new = p_x0 + num / den;
53
Division by zero
193 }
194
195 /* ignore crossings before current x */
196 if (x_new < x ||
44
Assuming 'x_new' is < 'x'
197 (!found_span_start && x_new < x0_min) ||
198 (found_span_start && x_new < x1_min))
199 continue;
45
Execution continues on line 156
200
201 crossing_value = establish_crossing_value(x_new, y,
202 p_x0, p_y0, p_x1, p_y1);
203
204 /* set nearest intersections as filled area endpoints */
205 if (!found_span_start &&
206 x_new < *x0 && crossing_value) {
207 /* nearer than first endpoint */
208 *x1 = *x0;
209 x1c = x0c;
210 *x0 = x_new;
211 x0c = 1;
212 } else if (!found_span_start &&
213 x_new == *x0 && crossing_value) {
214 /* same as first endpoint */
215 x0c++;
216 } else if (x_new < *x1 && crossing_value) {
217 /* nearer than second endpoint */
218 *x1 = x_new;
219 x1c = 1;
220 } else if (x_new == *x1 && crossing_value) {
221 /* same as second endpoint */
222 x1c++;
223 }
224 }
225 /* check whether the span endpoints have been found */
226 if (!found_span_start && x0c % 2 == 1) {
227 /* valid fill start found */
228 found_span_start = true1;
229
230 }
231 if (x1c % 2 == 1) {
232 /* valid fill endpoint found */
233 if (!found_span_start) {
234 /* not got a start yet; use this as start */
235 found_span_start = true1;
236 x0c = x1c;
237 *x0 = *x1;
238 } else {
239 /* got valid end of span */
240 return true1;
241 }
242 }
243 /* if current positions aren't valid endpoints, set new
244 * minimums after current positions */
245 if (!found_span_start)
246 x0_min = *x0 + 1;
247 x1_min = *x1 + 1;
248
249 } while (*x1 != NO_MAX);
250
251 /* no spans found */
252 return false0;
253}
254
255
256/**
257 * Plot a polygon
258 *
259 * \param nsfb framebuffer context
260 * \param p array of polygon vertices (x1, y1, x2, y2, ... , xN, yN)
261 * \param n number of polygon vertices (N)
262 * \param c fill colour
263 * \return true if no errors
264 */
265static bool_Bool polygon(nsfb_t *nsfb, const int *p, unsigned int n, nsfb_colour_t c)
266{
267 int poly_x0, poly_y0; /* Bounding box top left corner */
268 int poly_x1, poly_y1; /* Bounding box bottom right corner */
269 int i, j; /* indexes */
270 int x0 = 0, x1 = 0; /* filled span extents */
271 int y; /* current y coordinate */
272 int y_max; /* bottom of plot area */
273 nsfb_bbox_t fline;
274 nsfb_plot_pen_t pen;
275
276 /* find no. of vertex values */
277 int v = n * 2;
278
279 /* Can't plot polygons with 2 or fewer vertices */
280 if (n <= 2)
15
Assuming 'n' is > 2
16
Taking false branch
281 return true1;
282
283 pen.stroke_colour = c;
284
285 /* Find polygon bounding box */
286 poly_x0 = poly_x1 = *p;
287 poly_y0 = poly_y1 = p[1];
288 for (i = 2; i < v; i = i + 2) {
17
Assuming 'i' is < 'v'
18
Loop condition is true. Entering loop body
25
Assuming 'i' is >= 'v'
289 j = i + 1;
290 if (p[i] < poly_x0)
19
Assuming the condition is false
20
Taking false branch
291 poly_x0 = p[i];
292 else if (p[i] > poly_x1)
21
Assuming the condition is true
22
Taking true branch
293 poly_x1 = p[i];
294 if (p[j] < poly_y0)
23
Assuming the condition is true
24
Taking true branch
295 poly_y0 = p[j];
296 else if (p[j] > poly_y1)
297 poly_y1 = p[j];
298 }
299
300 /* Don't try to plot it if it's outside the clip rectangle */
301 if (nsfb->clip.y1 < poly_y0 ||
26
Assuming 'poly_y0' is <= field 'y1'
30
Taking false branch
302 nsfb->clip.y0 > poly_y1 ||
27
Assuming 'poly_y1' is >= field 'y0'
303 nsfb->clip.x1 < poly_x0 ||
28
Assuming 'poly_x0' is <= field 'x1'
304 nsfb->clip.x0 > poly_x1)
29
Assuming 'poly_x1' is >= field 'x0'
305 return true1;
306
307 /* Find the top of the important area */
308 if (poly_y0 > nsfb->clip.y0)
31
Assuming 'poly_y0' is > field 'y0'
32
Taking true branch
309 y = poly_y0;
310 else
311 y = nsfb->clip.y0;
312
313 /* Find the bottom of the important area */
314 if (poly_y1 < nsfb->clip.y1)
33
Assuming 'poly_y1' is < field 'y1'
34
Taking true branch
315 y_max = poly_y1;
316 else
317 y_max = nsfb->clip.y1;
318
319 for (; y
34.1
'y' is < 'y_max'
< y_max; y++) {
35
Loop condition is true. Entering loop body
320 x1 = poly_x0 - 1;
321 /* For each row */
322 while (find_span(p, v, x1 + 1, y, &x0, &x1)) {
36
Calling 'find_span'
323 /* don't draw anything outside clip region */
324 if (x1 < nsfb->clip.x0)
325 continue;
326 else if (x0 < nsfb->clip.x0)
327 x0 = nsfb->clip.x0;
328 if (x0 > nsfb->clip.x1)
329 break;
330 else if (x1 > nsfb->clip.x1)
331 x1 = nsfb->clip.x1;
332
333 fline.x0 = x0;
334 fline.y0 = y;
335 fline.x1 = x1;
336 fline.y1 = y;
337
338 /* draw this filled span on current row */
339 nsfb->plotter_fns->line(nsfb, 1, &fline, &pen);
340
341 /* don't look for more spans if already at end of clip
342 * region or polygon */
343 if (x1 == nsfb->clip.x1 || x1 == poly_x1)
344 break;
345 }
346 }
347 return true1;
348}
349
350static bool_Bool
351rectangle(nsfb_t *nsfb, nsfb_bbox_t *rect,
352 int line_width, nsfb_colour_t c,
353 bool_Bool dotted, bool_Bool dashed)
354{
355 nsfb_bbox_t side[4];
356 nsfb_plot_pen_t pen;
357
358 pen.stroke_colour = c;
359 pen.stroke_width = line_width;
360 if (dotted || dashed) {
361 pen.stroke_type = NFSB_PLOT_OPTYPE_PATTERN;
362 } else {
363 pen.stroke_type = NFSB_PLOT_OPTYPE_SOLID;
364 }
365
366 side[0] = *rect;
367 side[1] = *rect;
368 side[2] = *rect;
369 side[3] = *rect;
370
371 side[0].y1 = side[0].y0;
372 side[1].y0 = side[1].y1;
373 side[2].x1 = side[2].x0;
374 side[3].x0 = side[3].x1;
375
376 return nsfb->plotter_fns->line(nsfb, 4, side, &pen);
377}
378
379/* plotter routine for ellipse points */
380static void
381ellipsepoints(nsfb_t *nsfb, int cx, int cy, int x, int y, nsfb_colour_t c)
382{
383 nsfb->plotter_fns->point(nsfb, cx + x, cy + y, c);
384 nsfb->plotter_fns->point(nsfb, cx - x, cy + y, c);
385 nsfb->plotter_fns->point(nsfb, cx + x, cy - y, c);
386 nsfb->plotter_fns->point(nsfb, cx - x, cy - y, c);
387}
388
389static void
390ellipsefill(nsfb_t *nsfb, int cx, int cy, int x, int y, nsfb_colour_t c)
391{
392 nsfb_bbox_t fline[2];
393 nsfb_plot_pen_t pen;
394
395 pen.stroke_colour = c;
396
397 fline[0].x0 = fline[1].x0 = cx - x;
398 fline[0].x1 = fline[1].x1 = cx + x;
399 fline[0].y0 = fline[0].y1 = cy + y;
400 fline[1].y0 = fline[1].y1 = cy - y;
401
402 nsfb->plotter_fns->line(nsfb, 2, fline, &pen);
403
404}
405
406#define ROUND(a)((int)(a+0.5)) ((int)(a+0.5))
407
408static bool_Bool
409ellipse_midpoint(nsfb_t *nsfb,
410 int cx,
411 int cy,
412 int rx,
413 int ry,
414 nsfb_colour_t c,
415 void (ellipsefn)(nsfb_t *nsfb, int cx, int cy, int x, int y, nsfb_colour_t c))
416{
417 int rx2 = rx * rx;
418 int ry2 = ry * ry;
419 int tworx2 = 2 * rx2;
420 int twory2 = 2 * ry2;
421 int p;
422 int x = 0;
423 int y = ry;
424 int px = 0;
425 int py = tworx2 * y;
426
427 ellipsefn(nsfb, cx, cy, x, y, c);
428
429 /* region 1 */
430 p = ROUND(ry2 - (rx2 * ry) + (0.25 * rx2))((int)(ry2 - (rx2 * ry) + (0.25 * rx2)+0.5));
431 while (px < py) {
432 x++;
433 px += twory2;
434 if (p <0) {
435 p+=ry2 + px;
436 } else {
437 y--;
438 py -= tworx2;
439 p+=ry2 + px - py;
440 }
441 ellipsefn(nsfb, cx, cy, x, y, c);
442 }
443
444 /* region 2 */
445 p = ROUND(ry2*(x+0.5)*(x+0.5) + rx2*(y-1)*(y-1) - rx2*ry2)((int)(ry2*(x+0.5)*(x+0.5) + rx2*(y-1)*(y-1) - rx2*ry2+0.5));
446 while (y > 0) {
447 y--;
448 py -= tworx2;
449 if (p > 0) {
450 p+=rx2 - py;
451 } else {
452 x++;
453 px += twory2;
454 p+=rx2 - py + px;
455 }
456 ellipsefn(nsfb, cx, cy, x, y, c);
457 }
458 return true1;
459}
460
461
462/* plotter routine for 8way circle symetry */
463static void
464circlepoints(nsfb_t *nsfb, int cx, int cy, int x, int y, nsfb_colour_t c)
465{
466 nsfb->plotter_fns->point(nsfb, cx + x, cy + y, c);
467 nsfb->plotter_fns->point(nsfb, cx - x, cy + y, c);
468 nsfb->plotter_fns->point(nsfb, cx + x, cy - y, c);
469 nsfb->plotter_fns->point(nsfb, cx - x, cy - y, c);
470 nsfb->plotter_fns->point(nsfb, cx + y, cy + x, c);
471 nsfb->plotter_fns->point(nsfb, cx - y, cy + x, c);
472 nsfb->plotter_fns->point(nsfb, cx + y, cy - x, c);
473 nsfb->plotter_fns->point(nsfb, cx - y, cy - x, c);
474}
475
476static void
477circlefill(nsfb_t *nsfb, int cx, int cy, int x, int y, nsfb_colour_t c)
478{
479 nsfb_bbox_t fline[4];
480 nsfb_plot_pen_t pen;
481
482 pen.stroke_colour = c;
483
484 fline[0].x0 = fline[1].x0 = cx - x;
485 fline[0].x1 = fline[1].x1 = cx + x;
486 fline[0].y0 = fline[0].y1 = cy + y;
487 fline[1].y0 = fline[1].y1 = cy - y;
488
489 fline[2].x0 = fline[3].x0 = cx - y;
490 fline[2].x1 = fline[3].x1 = cx + y;
491 fline[2].y0 = fline[2].y1 = cy + x;
492 fline[3].y0 = fline[3].y1 = cy - x;
493
494 nsfb->plotter_fns->line(nsfb, 4, fline, &pen);
495}
496
497static bool_Bool circle_midpoint(nsfb_t *nsfb,
498 int cx,
499 int cy,
500 int r,
501 nsfb_colour_t c,
502 void (circfn)(nsfb_t *nsfb, int cx, int cy, int x, int y, nsfb_colour_t c))
503{
504 int x = 0;
505 int y = r;
506 int p = 1 - r;
507
508 circfn(nsfb, cx, cy, x, y, c);
509 while (x < y) {
510 x++;
511 if (p < 0) {
512 p += 2 * x + 1;
513 } else {
514 y--;
515 p += 2 * (x - y) + 1;
516 }
517 circfn(nsfb, cx, cy, x, y, c);
518 }
519 return true1;
520}
521
522static bool_Bool ellipse(nsfb_t *nsfb, nsfb_bbox_t *ellipse, nsfb_colour_t c)
523{
524 int width = (ellipse->x1 - ellipse->x0)>>1;
525 int height = (ellipse->y1 - ellipse->y0)>>1;
526
527 if (width == height) {
528 /* circle */
529 return circle_midpoint(nsfb, ellipse->x0 + width,
530 ellipse->y0 + height, width, c, circlepoints);
531 } else {
532 return ellipse_midpoint(nsfb, ellipse->x0 + width,
533 ellipse->y0 + height, width, height, c,
534 ellipsepoints);
535 }
536}
537
538static bool_Bool ellipse_fill(nsfb_t *nsfb, nsfb_bbox_t *ellipse, nsfb_colour_t c)
539{
540 int width = (ellipse->x1 - ellipse->x0) >> 1;
541 int height = (ellipse->y1 - ellipse->y0) >> 1;
542
543 if (width == height) {
544 /* circle */
545 return circle_midpoint(nsfb, ellipse->x0 + width,
546 ellipse->y0 + height, width, c, circlefill);
547 } else {
548 return ellipse_midpoint(nsfb, ellipse->x0 + width,
549 ellipse->y0 + height, width, height, c,
550 ellipsefill);
551 }
552}
553
554
555
556/* copy an area of surface from one location to another.
557 *
558 * @warning This implementation is woefully incomplete!
559 */
560static bool_Bool
561copy(nsfb_t *nsfb, nsfb_bbox_t *srcbox, nsfb_bbox_t *dstbox)
562{
563 int srcx = srcbox->x0;
564 int srcy = srcbox->y0;
565 int dstx = dstbox->x0;
566 int dsty = dstbox->y0;
567 int width = dstbox->x1 - dstbox->x0;
568 int height = dstbox->y1 - dstbox->y0;
569 uint8_t *srcptr;
570 uint8_t *dstptr;
571 int hloop;
572 nsfb_bbox_t allbox;
573
574 nsfb_plot_add_rect(srcbox, dstbox, &allbox);
575
576 nsfb->surface_rtns->claim(nsfb, &allbox);
577
578 srcptr = (nsfb->ptr +
579 (srcy * nsfb->linelen) +
580 ((srcx * nsfb->bpp) / 8));
581
582 dstptr = (nsfb->ptr +
583 (dsty * nsfb->linelen) +
584 ((dstx * nsfb->bpp) / 8));
585
586
587 if (width == nsfb->width) {
588 /* take shortcut and use memmove */
589 memmove(dstptr, srcptr, (width * height * nsfb->bpp) / 8);
590 } else {
591 if (srcy > dsty) {
592 for (hloop = height; hloop > 0; hloop--) {
593 memmove(dstptr, srcptr, (width * nsfb->bpp) / 8);
594 srcptr += nsfb->linelen;
595 dstptr += nsfb->linelen;
596 }
597 } else {
598 srcptr += height * nsfb->linelen;
599 dstptr += height * nsfb->linelen;
600 for (hloop = height; hloop > 0; hloop--) {
601 srcptr -= nsfb->linelen;
602 dstptr -= nsfb->linelen;
603 memmove(dstptr, srcptr, (width * nsfb->bpp) / 8);
604 }
605 }
606 }
607
608 nsfb->surface_rtns->update(nsfb, dstbox);
609
610 return true1;
611}
612
613
614
615static bool_Bool arc(nsfb_t *nsfb, int x, int y, int radius, int angle1,
616 int angle2, nsfb_colour_t c)
617{
618 (void)nsfb;
619 (void)x;
620 (void)y;
621 (void)radius;
622 (void)c;
623 (void)angle1;
624 (void)angle2;
625 return true1;
626}
627
628#define N_SEG30 30
629
630static int
631cubic_points(unsigned int pointc,
632 nsfb_point_t *point,
633 nsfb_bbox_t *curve,
634 nsfb_point_t *ctrla,
635 nsfb_point_t *ctrlb)
636{
637 unsigned int seg_loop;
638 double t;
639 double one_minus_t;
640 double a;
641 double b;
642 double c;
643 double d;
644 double x;
645 double y;
646 int cur_point;
647
648 point[0].x = curve->x0;
649 point[0].y = curve->y0;
650 cur_point = 1;
651 pointc--;
652
653 for (seg_loop = 1; seg_loop < pointc; ++seg_loop) {
654 t = (double)seg_loop / (double)pointc;
655
656 one_minus_t = 1.0 - t;
657
658 a = one_minus_t * one_minus_t * one_minus_t;
659 b = 3.0 * t * one_minus_t * one_minus_t;
660 c = 3.0 * t * t * one_minus_t;
661 d = t * t * t;
662
663 x = a * curve->x0 + b * ctrla->x + c * ctrlb->x + d * curve->x1;
664 y = a * curve->y0 + b * ctrla->y + c * ctrlb->y + d * curve->y1;
665
666 point[cur_point].x = x;
667 point[cur_point].y = y;
668 if ((point[cur_point].x != point[cur_point - 1].x) ||
669 (point[cur_point].y != point[cur_point - 1].y))
670 cur_point++;
671 }
672
673 point[cur_point].x = curve->x1;
674 point[cur_point].y = curve->y1;
675 if ((point[cur_point].x != point[cur_point - 1].x) ||
676 (point[cur_point].y != point[cur_point - 1].y))
677 cur_point++;
678
679 return cur_point;
680}
681
682/* calculate a series of points which describe a quadratic bezier spline.
683 *
684 * fills an array of points with values describing a quadratic curve. Both the
685 * start and end points are included as the first and last points
686 * respectively. Only if the next point on the curve is different from its
687 * predecessor is the point added which ensures points for the same position
688 * are not repeated.
689 */
690static int
691quadratic_points(unsigned int pointc,
692 nsfb_point_t *point,
693 nsfb_bbox_t *curve,
694 nsfb_point_t *ctrla)
695{
696 unsigned int seg_loop;
697 double t;
698 double one_minus_t;
699 double a;
700 double b;
701 double c;
702 double x;
703 double y;
704 int cur_point;
705
706 point[0].x = curve->x0;
707 point[0].y = curve->y0;
708 cur_point = 1;
709 pointc--; /* we have added the start point, one less point in the curve */
710
711 for (seg_loop = 1; seg_loop < pointc; ++seg_loop) {
712 t = (double)seg_loop / (double)pointc;
713
714 one_minus_t = 1.0 - t;
715
716 a = one_minus_t * one_minus_t;
717 b = 2.0 * t * one_minus_t;
718 c = t * t;
719
720 x = a * curve->x0 + b * ctrla->x + c * curve->x1;
721 y = a * curve->y0 + b * ctrla->y + c * curve->y1;
722
723 point[cur_point].x = x;
724 point[cur_point].y = y;
725 if ((point[cur_point].x != point[cur_point - 1].x) ||
726 (point[cur_point].y != point[cur_point - 1].y))
727 cur_point++;
728 }
729
730 point[cur_point].x = curve->x1;
731 point[cur_point].y = curve->y1;
732 if ((point[cur_point].x != point[cur_point - 1].x) ||
733 (point[cur_point].y != point[cur_point - 1].y))
734 cur_point++;
735
736 return cur_point;
737}
738
739static bool_Bool
740polylines(nsfb_t *nsfb,
741 int pointc,
742 const nsfb_point_t *points,
743 nsfb_plot_pen_t *pen)
744{
745 int point_loop;
746 nsfb_bbox_t line;
747
748 if (pen->stroke_type != NFSB_PLOT_OPTYPE_NONE) {
749 for (point_loop = 0; point_loop < (pointc - 1); point_loop++) {
750 line = *(nsfb_bbox_t *)&points[point_loop];
751 nsfb->plotter_fns->line(nsfb, 1, &line, pen);
752 }
753 }
754 return true1;
755}
756
757
758
759static bool_Bool
760quadratic(nsfb_t *nsfb,
761 nsfb_bbox_t *curve,
762 nsfb_point_t *ctrla,
763 nsfb_plot_pen_t *pen)
764{
765 nsfb_point_t points[N_SEG30];
766
767 if (pen->stroke_type == NFSB_PLOT_OPTYPE_NONE)
768 return false0;
769
770 return polylines(nsfb, quadratic_points(N_SEG30, points, curve, ctrla),
771 points, pen);
772}
773
774static bool_Bool
775cubic(nsfb_t *nsfb,
776 nsfb_bbox_t *curve,
777 nsfb_point_t *ctrla,
778 nsfb_point_t *ctrlb,
779 nsfb_plot_pen_t *pen)
780{
781 nsfb_point_t points[N_SEG30];
782
783 if (pen->stroke_type == NFSB_PLOT_OPTYPE_NONE)
784 return false0;
785
786 return polylines(nsfb, cubic_points(N_SEG30, points, curve, ctrla,ctrlb),
787 points, pen);
788}
789
790
791static bool_Bool
792path(nsfb_t *nsfb, int pathc, nsfb_plot_pathop_t *pathop, nsfb_plot_pen_t *pen)
793{
794 int path_loop;
795 nsfb_point_t *pts;
796 nsfb_point_t *curpt;
797 int ptc = 0;
798 nsfb_bbox_t curve;
799 nsfb_point_t ctrla;
800 nsfb_point_t ctrlb;
801 int added_count = 0;
802 int bpts;
803
804 /* count the verticies in the path and add N_SEG extra for curves */
805 for (path_loop = 0; path_loop < pathc; path_loop++) {
1
Assuming 'path_loop' is < 'pathc'
2
Loop condition is true. Entering loop body
4
Assuming 'path_loop' is >= 'pathc'
5
Loop condition is false. Execution continues on line 814
806 ptc++;
807 if ((pathop[path_loop].operation == NFSB_PLOT_PATHOP_QUAD) ||
3
Assuming field 'operation' is equal to NFSB_PLOT_PATHOP_QUAD
808 (pathop[path_loop].operation ==
809 NFSB_PLOT_PATHOP_CUBIC))
810 ptc += N_SEG30;
811 }
812
813 /* allocate storage for the vertexes */
814 curpt = pts = malloc(ptc * sizeof(nsfb_point_t));
815 if (curpt == NULL((void*)0)) {
6
Assuming 'curpt' is not equal to NULL
7
Taking false branch
816 return false0;
817 }
818
819 for (path_loop = 0; path_loop < pathc; path_loop++) {
8
Loop condition is true. Entering loop body
11
Loop condition is false. Execution continues on line 859
820 switch (pathop[path_loop].operation) {
9
Control jumps to 'case NFSB_PLOT_PATHOP_QUAD:' at line 821
821 case NFSB_PLOT_PATHOP_QUAD:
822 curpt-=2;
823 added_count -= 2;
824 curve.x0 = pathop[path_loop - 2].point.x;
825 curve.y0 = pathop[path_loop - 2].point.y;
826 ctrla.x = pathop[path_loop - 1].point.x;
827 ctrla.y = pathop[path_loop - 1].point.y;
828 curve.x1 = pathop[path_loop].point.x;
829 curve.y1 = pathop[path_loop].point.y;
830 bpts = quadratic_points(N_SEG30, curpt, &curve, &ctrla);
831 curpt += bpts;
832 added_count += bpts;
833 break;
10
Execution continues on line 819
834
835 case NFSB_PLOT_PATHOP_CUBIC:
836 curpt-=3;
837 added_count -=3;
838 curve.x0 = pathop[path_loop - 3].point.x;
839 curve.y0 = pathop[path_loop - 3].point.y;
840 ctrla.x = pathop[path_loop - 2].point.x;
841 ctrla.y = pathop[path_loop - 2].point.y;
842 ctrlb.x = pathop[path_loop - 1].point.x;
843 ctrlb.y = pathop[path_loop - 1].point.y;
844 curve.x1 = pathop[path_loop].point.x;
845 curve.y1 = pathop[path_loop].point.y;
846 bpts = cubic_points(N_SEG30, curpt, &curve, &ctrla, &ctrlb);
847 curpt += bpts;
848 added_count += bpts;
849 break;
850
851 default:
852 *curpt = pathop[path_loop].point;
853 curpt++;
854 added_count ++;
855 break;
856 }
857 }
858
859 if (pen->fill_type != NFSB_PLOT_OPTYPE_NONE) {
12
Assuming field 'fill_type' is not equal to NFSB_PLOT_OPTYPE_NONE
13
Taking true branch
860 polygon(nsfb, (int *)pts, added_count, pen->fill_colour);
14
Calling 'polygon'
861 }
862
863 if (pen->stroke_type != NFSB_PLOT_OPTYPE_NONE) {
864 polylines(nsfb, added_count, pts, pen);
865 }
866
867 free(pts);
868
869 return true1;
870}
871
872bool_Bool select_plotters(nsfb_t *nsfb)
873{
874 const nsfb_plotter_fns_t *table = NULL((void*)0);
875
876 switch (nsfb->format) {
877
878 case NSFB_FMT_XBGR8888: /* 32bpp Unused Blue Green Red */
879 case NSFB_FMT_ABGR8888: /* 32bpp Alpha Blue Green Red */
880 table = &_nsfb_32bpp_xbgr8888_plotters;
881 nsfb->bpp = 32;
882 break;
883
884 case NSFB_FMT_XRGB8888: /* 32bpp Unused Red Green Blue */
885 case NSFB_FMT_ARGB8888: /* 32bpp Alpha Red Green Blue */
886 table = &_nsfb_32bpp_xrgb8888_plotters;
887 nsfb->bpp = 32;
888 break;
889
890
891 case NSFB_FMT_RGB888: /* 24 bpp Alpha Red Green Blue */
892#ifdef ENABLE_24_BPP
893 table = &_nsfb_24bpp_plotters;
894 nsfb->bpp = 24;
895 break;
896#else
897 return false0;
898#endif
899
900 case NSFB_FMT_ARGB1555: /* 16 bpp 555 */
901 case NSFB_FMT_RGB565: /* 16 bpp 565 */
902 table = &_nsfb_16bpp_plotters;
903 nsfb->bpp = 16;
904 break;
905
906 case NSFB_FMT_I8: /* 8bpp indexed */
907 table = &_nsfb_8bpp_plotters;
908 nsfb->bpp = 8;
909 break;
910
911 case NSFB_FMT_I1: /* black and white */
912#ifdef ENABLE_1_BPP
913 table = &_nsfb_1bpp_plotters;
914 nsfb->bpp = 1
915 break;
916#else
917 return false0;
918#endif
919
920 case NSFB_FMT_ANY: /* No specific format - use surface default */
921 default:
922 return false0;
923 }
924
925 if (nsfb->plotter_fns != NULL((void*)0)) {
926 free(nsfb->plotter_fns);
927 }
928
929 nsfb->plotter_fns = calloc(1, sizeof(nsfb_plotter_fns_t));
930 if (nsfb->plotter_fns == NULL((void*)0)) {
931 return false0;
932 }
933
934 memcpy(nsfb->plotter_fns, table, sizeof(nsfb_plotter_fns_t));
935
936 /* set the generics */
937 nsfb->plotter_fns->clg = clg;
938 nsfb->plotter_fns->set_clip = set_clip;
939 nsfb->plotter_fns->get_clip = get_clip;
940 nsfb->plotter_fns->polygon = polygon;
941 nsfb->plotter_fns->rectangle = rectangle;
942 nsfb->plotter_fns->ellipse = ellipse;
943 nsfb->plotter_fns->ellipse_fill = ellipse_fill;
944 nsfb->plotter_fns->copy = copy;
945 nsfb->plotter_fns->arc = arc;
946 nsfb->plotter_fns->quadratic = quadratic;
947 nsfb->plotter_fns->cubic = cubic;
948 nsfb->plotter_fns->path = path;
949 nsfb->plotter_fns->polylines = polylines;
950
951 /* set default clip rectangle to size of framebuffer */
952 nsfb->clip.x0 = 0;
953 nsfb->clip.y0 = 0;
954 nsfb->clip.x1 = nsfb->width;
955 nsfb->clip.y1 = nsfb->height;
956
957 return true1;
958}
959
960/*
961 * Local variables:
962 * c-basic-offset: 4
963 * tab-width: 8
964 * End:
965 */