1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
|
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Adaptation for 32-bit screen coordinates (scanline32_u) has been sponsored by
// Liberty Technology Systems, Inc., visit http://lib-sys.com
//
// Liberty Technology Systems, Inc. is the provider of
// PostScript and PDF technology for software developers.
//
//----------------------------------------------------------------------------
#ifndef AGG_SCANLINE_U_INCLUDED
#define AGG_SCANLINE_U_INCLUDED
#include "agg_array.h"
namespace agg
{
//=============================================================scanline_u8
//
// Unpacked scanline container class
//
// This class is used to transfer data from a scanline rasterizer
// to the rendering buffer. It's organized very simple. The class stores
// information of horizontal spans to render it into a pixel-map buffer.
// Each span has staring X, length, and an array of bytes that determine the
// cover-values for each pixel.
// Before using this class you should know the minimal and maximal pixel
// coordinates of your scanline. The protocol of using is:
// 1. reset(min_x, max_x)
// 2. add_cell() / add_span() - accumulate scanline.
// When forming one scanline the next X coordinate must be always greater
// than the last stored one, i.e. it works only with ordered coordinates.
// 3. Call finalize(y) and render the scanline.
// 3. Call reset_spans() to prepare for the new scanline.
//
// 4. Rendering:
//
// Scanline provides an iterator class that allows you to extract
// the spans and the cover values for each pixel. Be aware that clipping
// has not been done yet, so you should perform it yourself.
// Use scanline_u8::iterator to render spans:
//-------------------------------------------------------------------------
//
// int y = sl.y(); // Y-coordinate of the scanline
//
// ************************************
// ...Perform vertical clipping here...
// ************************************
//
// scanline_u8::const_iterator span = sl.begin();
//
// unsigned char* row = m_rbuf->row(y); // The address of the beginning
// // of the current row
//
// unsigned num_spans = sl.num_spans(); // Number of spans. It's guaranteed that
// // num_spans is always greater than 0.
//
// do
// {
// const scanline_u8::cover_type* covers =
// span->covers; // The array of the cover values
//
// int num_pix = span->len; // Number of pixels of the span.
// // Always greater than 0, still it's
// // better to use "int" instead of
// // "unsigned" because it's more
// // convenient for clipping
// int x = span->x;
//
// **************************************
// ...Perform horizontal clipping here...
// ...you have x, covers, and pix_count..
// **************************************
//
// unsigned char* dst = row + x; // Calculate the start address of the row.
// // In this case we assume a simple
// // grayscale image 1-byte per pixel.
// do
// {
// *dst++ = *covers++; // Hypotetical rendering.
// }
// while(--num_pix);
//
// ++span;
// }
// while(--num_spans); // num_spans cannot be 0, so this loop is quite safe
//------------------------------------------------------------------------
//
// The question is: why should we accumulate the whole scanline when we
// could render just separate spans when they're ready?
// That's because using the scanline is generally faster. When is consists
// of more than one span the conditions for the processor cash system
// are better, because switching between two different areas of memory
// (that can be very large) occurs less frequently.
//------------------------------------------------------------------------
class scanline_u8
{
public:
typedef scanline_u8 self_type;
typedef int8u cover_type;
typedef int16 coord_type;
//--------------------------------------------------------------------
struct span
{
coord_type x;
coord_type len;
cover_type* covers;
};
typedef span* iterator;
typedef const span* const_iterator;
//--------------------------------------------------------------------
scanline_u8() :
m_min_x(0),
m_last_x(0x7FFFFFF0),
m_cur_span(0)
{}
//--------------------------------------------------------------------
void reset(int min_x, int max_x)
{
unsigned max_len = max_x - min_x + 2;
if(max_len > m_spans.size())
{
m_spans.resize(max_len);
m_covers.resize(max_len);
}
m_last_x = 0x7FFFFFF0;
m_min_x = min_x;
m_cur_span = &m_spans[0];
}
//--------------------------------------------------------------------
void add_cell(int x, unsigned cover)
{
x -= m_min_x;
m_covers[x] = (cover_type)cover;
if(x == m_last_x+1)
{
m_cur_span->len++;
}
else
{
m_cur_span++;
m_cur_span->x = (coord_type)(x + m_min_x);
m_cur_span->len = 1;
m_cur_span->covers = &m_covers[x];
}
m_last_x = x;
}
//--------------------------------------------------------------------
void add_cells(int x, unsigned len, const cover_type* covers)
{
x -= m_min_x;
memcpy(&m_covers[x], covers, len * sizeof(cover_type));
if(x == m_last_x+1)
{
m_cur_span->len += (coord_type)len;
}
else
{
m_cur_span++;
m_cur_span->x = (coord_type)(x + m_min_x);
m_cur_span->len = (coord_type)len;
m_cur_span->covers = &m_covers[x];
}
m_last_x = x + len - 1;
}
//--------------------------------------------------------------------
void add_span(int x, unsigned len, unsigned cover)
{
x -= m_min_x;
memset(&m_covers[x], cover, len);
if(x == m_last_x+1)
{
m_cur_span->len += (coord_type)len;
}
else
{
m_cur_span++;
m_cur_span->x = (coord_type)(x + m_min_x);
m_cur_span->len = (coord_type)len;
m_cur_span->covers = &m_covers[x];
}
m_last_x = x + len - 1;
}
//--------------------------------------------------------------------
void finalize(int y)
{
m_y = y;
}
//--------------------------------------------------------------------
void reset_spans()
{
m_last_x = 0x7FFFFFF0;
m_cur_span = &m_spans[0];
}
//--------------------------------------------------------------------
int y() const { return m_y; }
unsigned num_spans() const { return unsigned(m_cur_span - &m_spans[0]); }
const_iterator begin() const { return &m_spans[1]; }
iterator begin() { return &m_spans[1]; }
private:
scanline_u8(const self_type&);
const self_type& operator = (const self_type&);
private:
int m_min_x;
int m_last_x;
int m_y;
pod_array<cover_type> m_covers;
pod_array<span> m_spans;
span* m_cur_span;
};
//==========================================================scanline_u8_am
//
// The scanline container with alpha-masking
//
//------------------------------------------------------------------------
template<class AlphaMask>
class scanline_u8_am : public scanline_u8
{
public:
typedef scanline_u8 base_type;
typedef AlphaMask alpha_mask_type;
typedef base_type::cover_type cover_type;
typedef base_type::coord_type coord_type;
scanline_u8_am() : base_type(), m_alpha_mask(0) {}
scanline_u8_am(AlphaMask& am) : base_type(), m_alpha_mask(&am) {}
//--------------------------------------------------------------------
void finalize(int span_y)
{
base_type::finalize(span_y);
if(m_alpha_mask)
{
typename base_type::iterator span = base_type::begin();
unsigned count = base_type::num_spans();
do
{
m_alpha_mask->combine_hspan(span->x,
base_type::y(),
span->covers,
span->len);
++span;
}
while(--count);
}
}
private:
AlphaMask* m_alpha_mask;
};
//===========================================================scanline32_u8
class scanline32_u8
{
public:
typedef scanline32_u8 self_type;
typedef int8u cover_type;
typedef int32 coord_type;
//--------------------------------------------------------------------
struct span
{
span() {}
span(coord_type x_, coord_type len_, cover_type* covers_) :
x(x_), len(len_), covers(covers_) {}
coord_type x;
coord_type len;
cover_type* covers;
};
typedef pod_bvector<span, 4> span_array_type;
//--------------------------------------------------------------------
class const_iterator
{
public:
const_iterator(const span_array_type& spans) :
m_spans(spans),
m_span_idx(0)
{}
const span& operator*() const { return m_spans[m_span_idx]; }
const span* operator->() const { return &m_spans[m_span_idx]; }
void operator ++ () { ++m_span_idx; }
private:
const span_array_type& m_spans;
unsigned m_span_idx;
};
//--------------------------------------------------------------------
class iterator
{
public:
iterator(span_array_type& spans) :
m_spans(spans),
m_span_idx(0)
{}
span& operator*() { return m_spans[m_span_idx]; }
span* operator->() { return &m_spans[m_span_idx]; }
void operator ++ () { ++m_span_idx; }
private:
span_array_type& m_spans;
unsigned m_span_idx;
};
//--------------------------------------------------------------------
scanline32_u8() :
m_min_x(0),
m_last_x(0x7FFFFFF0),
m_covers()
{}
//--------------------------------------------------------------------
void reset(int min_x, int max_x)
{
unsigned max_len = max_x - min_x + 2;
if(max_len > m_covers.size())
{
m_covers.resize(max_len);
}
m_last_x = 0x7FFFFFF0;
m_min_x = min_x;
m_spans.remove_all();
}
//--------------------------------------------------------------------
void add_cell(int x, unsigned cover)
{
x -= m_min_x;
m_covers[x] = cover_type(cover);
if(x == m_last_x+1)
{
m_spans.last().len++;
}
else
{
m_spans.add(span(coord_type(x + m_min_x), 1, &m_covers[x]));
}
m_last_x = x;
}
//--------------------------------------------------------------------
void add_cells(int x, unsigned len, const cover_type* covers)
{
x -= m_min_x;
memcpy(&m_covers[x], covers, len * sizeof(cover_type));
if(x == m_last_x+1)
{
m_spans.last().len += coord_type(len);
}
else
{
m_spans.add(span(coord_type(x + m_min_x),
coord_type(len),
&m_covers[x]));
}
m_last_x = x + len - 1;
}
//--------------------------------------------------------------------
void add_span(int x, unsigned len, unsigned cover)
{
x -= m_min_x;
memset(&m_covers[x], cover, len);
if(x == m_last_x+1)
{
m_spans.last().len += coord_type(len);
}
else
{
m_spans.add(span(coord_type(x + m_min_x),
coord_type(len),
&m_covers[x]));
}
m_last_x = x + len - 1;
}
//--------------------------------------------------------------------
void finalize(int y)
{
m_y = y;
}
//--------------------------------------------------------------------
void reset_spans()
{
m_last_x = 0x7FFFFFF0;
m_spans.remove_all();
}
//--------------------------------------------------------------------
int y() const { return m_y; }
unsigned num_spans() const { return m_spans.size(); }
const_iterator begin() const { return const_iterator(m_spans); }
iterator begin() { return iterator(m_spans); }
private:
scanline32_u8(const self_type&);
const self_type& operator = (const self_type&);
private:
int m_min_x;
int m_last_x;
int m_y;
pod_array<cover_type> m_covers;
span_array_type m_spans;
};
//========================================================scanline32_u8_am
//
// The scanline container with alpha-masking
//
//------------------------------------------------------------------------
template<class AlphaMask>
class scanline32_u8_am : public scanline32_u8
{
public:
typedef scanline32_u8 base_type;
typedef AlphaMask alpha_mask_type;
typedef base_type::cover_type cover_type;
typedef base_type::coord_type coord_type;
scanline32_u8_am() : base_type(), m_alpha_mask(0) {}
scanline32_u8_am(AlphaMask& am) : base_type(), m_alpha_mask(&am) {}
//--------------------------------------------------------------------
void finalize(int span_y)
{
base_type::finalize(span_y);
if(m_alpha_mask)
{
typename base_type::iterator span = base_type::begin();
unsigned count = base_type::num_spans();
do
{
m_alpha_mask->combine_hspan(span->x,
base_type::y(),
span->covers,
span->len);
++span;
}
while(--count);
}
}
private:
AlphaMask* m_alpha_mask;
};
}
#endif
|