Blender  V2.93
bitmap_draw_2d.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  *
19  * The Original Code is: some of this file.
20  */
21 
28 #include <limits.h>
29 
30 #include "MEM_guardedalloc.h"
31 
32 #include "BLI_bitmap_draw_2d.h"
33 
34 #include "BLI_math_base.h"
35 #include "BLI_sort.h"
36 #include "BLI_utildefines.h"
37 
38 #include "BLI_strict_flags.h"
39 
40 /* -------------------------------------------------------------------- */
49 void BLI_bitmap_draw_2d_line_v2v2i(const int p1[2],
50  const int p2[2],
51  bool (*callback)(int, int, void *),
52  void *user_data)
53 {
54  /* Bresenham's line algorithm. */
55  int x1 = p1[0];
56  int y1 = p1[1];
57  int x2 = p2[0];
58  int y2 = p2[1];
59 
60  if (callback(x1, y1, user_data) == 0) {
61  return;
62  }
63 
64  /* if x1 == x2 or y1 == y2, then it does not matter what we set here */
65  const int sign_x = (x2 > x1) ? 1 : -1;
66  const int sign_y = (y2 > y1) ? 1 : -1;
67 
68  const int delta_x = (sign_x == 1) ? (x2 - x1) : (x1 - x2);
69  const int delta_y = (sign_y == 1) ? (y2 - y1) : (y1 - y2);
70 
71  const int delta_x_step = delta_x * 2;
72  const int delta_y_step = delta_y * 2;
73 
74  if (delta_x >= delta_y) {
75  /* error may go below zero */
76  int error = delta_y_step - delta_x;
77 
78  while (x1 != x2) {
79  if (error >= 0) {
80  if (error || (sign_x == 1)) {
81  y1 += sign_y;
82  error -= delta_x_step;
83  }
84  /* else do nothing */
85  }
86  /* else do nothing */
87 
88  x1 += sign_x;
89  error += delta_y_step;
90 
91  if (callback(x1, y1, user_data) == 0) {
92  return;
93  }
94  }
95  }
96  else {
97  /* error may go below zero */
98  int error = delta_x_step - delta_y;
99 
100  while (y1 != y2) {
101  if (error >= 0) {
102  if (error || (sign_y == 1)) {
103  x1 += sign_x;
104  error -= delta_y_step;
105  }
106  /* else do nothing */
107  }
108  /* else do nothing */
109 
110  y1 += sign_y;
111  error += delta_x_step;
112 
113  if (callback(x1, y1, user_data) == 0) {
114  return;
115  }
116  }
117  }
118 }
119 
122 /* -------------------------------------------------------------------- */
142 /* Macros could be moved to a shared location. */
143 #define ORDERED_SWAP(ty, a, b) \
144  if (a > b) { \
145  SWAP(ty, a, b); \
146  } \
147  ((void)0)
148 
149 #define ORDERED_SWAP_BY(ty, a, b, by) \
150  if ((a by) > (b by)) { \
151  SWAP(ty, a, b); \
152  } \
153  ((void)0)
154 
155 #define ORDER_VARS2(ty, a, b) \
156  { \
157  ORDERED_SWAP(ty, a, b); \
158  } \
159  ((void)0)
160 
161 #define ORDER_VARS3_BY(ty, a, b, c, by) \
162  { \
163  ORDERED_SWAP_BY(ty, b, c, by); \
164  ORDERED_SWAP_BY(ty, a, c, by); \
165  ORDERED_SWAP_BY(ty, a, b, by); \
166  } \
167  ((void)0)
168 
169 static float inv_slope(const int a[2], const int b[2])
170 {
171  return ((float)(a[0] - b[0]) / (float)(a[1] - b[1]));
172 }
173 
181 static void draw_tri_flat_max(const int p[2],
182  const int max_y,
183  const float inv_slope1,
184  const float inv_slope2,
185  void (*callback)(int x, int x_end, int y, void *),
186  void *user_data)
187 {
188  float cur_x1 = (float)p[0];
189  float cur_x2 = cur_x1;
190  /* start-end inclusive */
191  const int min_y = p[1];
192  const int max_y_end = max_y + 1;
193  for (int scanline_y = min_y; scanline_y != max_y_end; scanline_y += 1) {
194  callback((int)cur_x1, 1 + (int)cur_x2, scanline_y, user_data);
195  cur_x1 += inv_slope1;
196  cur_x2 += inv_slope2;
197  }
198 }
199 
207 static void draw_tri_flat_min(const int p[2],
208  const int min_y,
209  const float inv_slope1,
210  const float inv_slope2,
211  void (*callback)(int x, int x_end, int y, void *),
212  void *user_data)
213 {
214  float cur_x1 = (float)p[0];
215  float cur_x2 = cur_x1;
216  /* start-end inclusive */
217  const int max_y = p[1];
218  const int min_y_end = min_y - 1;
219  for (int scanline_y = max_y; scanline_y != min_y_end; scanline_y -= 1) {
220  callback((int)cur_x1, 1 + (int)cur_x2, scanline_y, user_data);
221  cur_x1 -= inv_slope1;
222  cur_x2 -= inv_slope2;
223  }
224 }
225 
230  /* all 2d */
231  const int p1[2],
232  const int p2[2],
233  const int p3[2],
234  void (*callback)(int x, int x_end, int y, void *),
235  void *user_data)
236 {
237  /* At first sort the three vertices by y-coordinate ascending so p1 is the top-most vertice */
238  ORDER_VARS3_BY(const int *, p1, p2, p3, [1]);
239 
240  BLI_assert(p1[1] <= p2[1] && p2[1] <= p3[1]);
241 
242  /* Check for trivial case of bottom-flat triangle. */
243  if (p2[1] == p3[1]) {
244  float inv_slope1 = inv_slope(p2, p1);
245  float inv_slope2 = inv_slope(p3, p1);
246  ORDER_VARS2(float, inv_slope1, inv_slope2);
247  BLI_assert(!(inv_slope1 > inv_slope2));
248  draw_tri_flat_max(p1, p2[1], inv_slope1, inv_slope2, callback, user_data);
249  }
250  else if (p1[1] == p2[1]) {
251  /* Check for trivial case of top-flat triangle. */
252  float inv_slope1 = inv_slope(p3, p1);
253  float inv_slope2 = inv_slope(p3, p2);
254  ORDER_VARS2(float, inv_slope2, inv_slope1);
255  BLI_assert(!(inv_slope1 < inv_slope2));
257  p2[1] + 1, /* avoid overlap */
258  inv_slope1,
259  inv_slope2,
260  callback,
261  user_data);
262  }
263  else {
264  /* General case - split the triangle in a top-flat and bottom-flat one. */
265  const float inv_slope_p21 = inv_slope(p2, p1);
266  const float inv_slope_p31 = inv_slope(p3, p1);
267  const float inv_slope_p32 = inv_slope(p3, p2);
268 
269  float inv_slope1_max, inv_slope2_max;
270  float inv_slope2_min, inv_slope1_min;
271 
272  if (inv_slope_p21 < inv_slope_p31) {
273  inv_slope1_max = inv_slope_p21;
274  inv_slope2_max = inv_slope_p31;
275  inv_slope2_min = inv_slope_p31;
276  inv_slope1_min = inv_slope_p32;
277  }
278  else {
279  inv_slope1_max = inv_slope_p31;
280  inv_slope2_max = inv_slope_p21;
281  inv_slope2_min = inv_slope_p32;
282  inv_slope1_min = inv_slope_p31;
283  }
284 
285  draw_tri_flat_max(p1, p2[1], inv_slope1_max, inv_slope2_max, callback, user_data);
287  p2[1] + 1, /* avoid overlap */
288  inv_slope1_min,
289  inv_slope2_min,
290  callback,
291  user_data);
292  }
293 }
294 
295 #undef ORDERED_SWAP
296 #undef ORDERED_SWAP_BY
297 #undef ORDER_VARS2
298 #undef ORDER_VARS3_BY
299 
302 /* -------------------------------------------------------------------- */
306 /* sort edge-segments on y, then x axis */
307 static int draw_poly_v2i_n__span_y_sort(const void *a_p, const void *b_p, void *verts_p)
308 {
309  const int(*verts)[2] = verts_p;
310  const int *a = a_p;
311  const int *b = b_p;
312  const int *co_a = verts[a[0]];
313  const int *co_b = verts[b[0]];
314 
315  if (co_a[1] < co_b[1]) {
316  return -1;
317  }
318  if (co_a[1] > co_b[1]) {
319  return 1;
320  }
321  if (co_a[0] < co_b[0]) {
322  return -1;
323  }
324  if (co_a[0] > co_b[0]) {
325  return 1;
326  }
327  /* co_a & co_b are identical, use the line closest to the x-min */
328  const int *co = co_a;
329  co_a = verts[a[1]];
330  co_b = verts[b[1]];
331  int ord = (((co_b[0] - co[0]) * (co_a[1] - co[1])) - ((co_a[0] - co[0]) * (co_b[1] - co[1])));
332  if (ord > 0) {
333  return -1;
334  }
335  if (ord < 0) {
336  return 1;
337  }
338  return 0;
339 }
340 
353 void BLI_bitmap_draw_2d_poly_v2i_n(const int xmin,
354  const int ymin,
355  const int xmax,
356  const int ymax,
357  const int verts[][2],
358  const int verts_len,
359  void (*callback)(int x, int x_end, int y, void *),
360  void *user_data)
361 {
362  /* Originally by Darel Rex Finley, 2007.
363  * Optimized by Campbell Barton, 2016 to track sorted intersections. */
364 
365  int(*span_y)[2] = MEM_mallocN(sizeof(*span_y) * (size_t)verts_len, __func__);
366  int span_y_len = 0;
367 
368  for (int i_curr = 0, i_prev = verts_len - 1; i_curr < verts_len; i_prev = i_curr++) {
369  const int *co_prev = verts[i_prev];
370  const int *co_curr = verts[i_curr];
371 
372  if (co_prev[1] != co_curr[1]) {
373  /* Any segments entirely above or below the area of interest can be skipped. */
374  if ((min_ii(co_prev[1], co_curr[1]) >= ymax) || (max_ii(co_prev[1], co_curr[1]) < ymin)) {
375  continue;
376  }
377 
378  int *s = span_y[span_y_len++];
379  if (co_prev[1] < co_curr[1]) {
380  s[0] = i_prev;
381  s[1] = i_curr;
382  }
383  else {
384  s[0] = i_curr;
385  s[1] = i_prev;
386  }
387  }
388  }
389 
390  BLI_qsort_r(
391  span_y, (size_t)span_y_len, sizeof(*span_y), draw_poly_v2i_n__span_y_sort, (void *)verts);
392 
393  struct NodeX {
394  int span_y_index;
395  int x;
396  } *node_x = MEM_mallocN(sizeof(*node_x) * (size_t)(verts_len + 1), __func__);
397  int node_x_len = 0;
398 
399  int span_y_index = 0;
400  if (span_y_len != 0 && verts[span_y[0][0]][1] < ymin) {
401  while ((span_y_index < span_y_len) && (verts[span_y[span_y_index][0]][1] < ymin)) {
402  BLI_assert(verts[span_y[span_y_index][0]][1] < verts[span_y[span_y_index][1]][1]);
403  if (verts[span_y[span_y_index][1]][1] >= ymin) {
404  struct NodeX *n = &node_x[node_x_len++];
405  n->span_y_index = span_y_index;
406  }
407  span_y_index += 1;
408  }
409  }
410 
411  /* Loop through the rows of the image. */
412  for (int pixel_y = ymin; pixel_y < ymax; pixel_y++) {
413  bool is_sorted = true;
414  bool do_remove = false;
415 
416  for (int i = 0, x_ix_prev = INT_MIN; i < node_x_len; i++) {
417  struct NodeX *n = &node_x[i];
418  const int *s = span_y[n->span_y_index];
419  const int *co_prev = verts[s[0]];
420  const int *co_curr = verts[s[1]];
421 
422  BLI_assert(co_prev[1] < pixel_y && co_curr[1] >= pixel_y);
423 
424  const double x = (co_prev[0] - co_curr[0]);
425  const double y = (co_prev[1] - co_curr[1]);
426  const double y_px = (pixel_y - co_curr[1]);
427  const int x_ix = (int)((double)co_curr[0] + ((y_px / y) * x));
428  n->x = x_ix;
429 
430  if (is_sorted && (x_ix_prev > x_ix)) {
431  is_sorted = false;
432  }
433  if (do_remove == false && co_curr[1] == pixel_y) {
434  do_remove = true;
435  }
436  x_ix_prev = x_ix;
437  }
438 
439  /* Sort the nodes, via a simple "Bubble" sort. */
440  if (is_sorted == false) {
441  int i = 0;
442  const int node_x_end = node_x_len - 1;
443  while (i < node_x_end) {
444  if (node_x[i].x > node_x[i + 1].x) {
445  SWAP(struct NodeX, node_x[i], node_x[i + 1]);
446  if (i != 0) {
447  i -= 1;
448  }
449  }
450  else {
451  i += 1;
452  }
453  }
454  }
455 
456  /* Fill the pixels between node pairs. */
457  for (int i = 0; i < node_x_len; i += 2) {
458  int x_src = node_x[i].x;
459  int x_dst = node_x[i + 1].x;
460 
461  if (x_src >= xmax) {
462  break;
463  }
464 
465  if (x_dst > xmin) {
466  if (x_src < xmin) {
467  x_src = xmin;
468  }
469  if (x_dst > xmax) {
470  x_dst = xmax;
471  }
472  /* for single call per x-span */
473  if (x_src < x_dst) {
474  callback(x_src - xmin, x_dst - xmin, pixel_y - ymin, user_data);
475  }
476  }
477  }
478 
479  /* Clear finalized nodes in one pass, only when needed
480  * (avoids excessive array-resizing). */
481  if (do_remove == true) {
482  int i_dst = 0;
483  for (int i_src = 0; i_src < node_x_len; i_src += 1) {
484  const int *s = span_y[node_x[i_src].span_y_index];
485  const int *co = verts[s[1]];
486  if (co[1] != pixel_y) {
487  if (i_dst != i_src) {
488  /* x is initialized for the next pixel_y (no need to adjust here) */
489  node_x[i_dst].span_y_index = node_x[i_src].span_y_index;
490  }
491  i_dst += 1;
492  }
493  }
494  node_x_len = i_dst;
495  }
496 
497  /* Scan for new x-nodes */
498  while ((span_y_index < span_y_len) && (verts[span_y[span_y_index][0]][1] == pixel_y)) {
499  /* note, node_x these are just added at the end,
500  * not ideal but sorting once will resolve. */
501 
502  /* x is initialized for the next pixel_y */
503  struct NodeX *n = &node_x[node_x_len++];
504  n->span_y_index = span_y_index;
505  span_y_index += 1;
506  }
507  }
508 
509  MEM_freeN(span_y);
510  MEM_freeN(node_x);
511 }
512 
typedef float(TangentPoint)[2]
#define BLI_assert(a)
Definition: BLI_assert.h:58
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
void BLI_qsort_r(void *a, size_t n, size_t es, BLI_sort_cmp_t cmp, void *thunk)
Definition: sort.c:95
Strict compiler flags for areas of code we want to ensure don't do conversions without us knowing abo...
#define SWAP(type, a, b)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble y1
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble x2
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
Read Guarded memory(de)allocation.
void BLI_bitmap_draw_2d_poly_v2i_n(const int xmin, const int ymin, const int xmax, const int ymax, const int verts[][2], const int verts_len, void(*callback)(int x, int x_end, int y, void *), void *user_data)
static int draw_poly_v2i_n__span_y_sort(const void *a_p, const void *b_p, void *verts_p)
static float inv_slope(const int a[2], const int b[2])
void BLI_bitmap_draw_2d_line_v2v2i(const int p1[2], const int p2[2], bool(*callback)(int, int, void *), void *user_data)
void BLI_bitmap_draw_2d_tri_v2i(const int p1[2], const int p2[2], const int p3[2], void(*callback)(int x, int x_end, int y, void *), void *user_data)
static void draw_tri_flat_max(const int p[2], const int max_y, const float inv_slope1, const float inv_slope2, void(*callback)(int x, int x_end, int y, void *), void *user_data)
static void draw_tri_flat_min(const int p[2], const int min_y, const float inv_slope1, const float inv_slope2, void(*callback)(int x, int x_end, int y, void *), void *user_data)
#define ORDER_VARS3_BY(ty, a, b, c, by)
#define ORDER_VARS2(ty, a, b)
void * user_data
DEGForeachIDComponentCallback callback
static float verts[][3]
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static void error(const char *str)
Definition: meshlaplacian.c:65
static unsigned a[3]
Definition: RandGen.cpp:92