1 //---------------------------------------------------------------------------- 2 // Anti-Grain Geometry - Version 2.2 3 // Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com) 4 // 5 // Permission to copy, use, modify, sell and distribute this software 6 // is granted provided this copyright notice appears in all copies. 7 // This software is provided "as is" without express or implied 8 // warranty, and with no claim as to its suitability for any purpose. 9 // 10 //---------------------------------------------------------------------------- 11 // Contact: mcseem@antigrain.com 12 // mcseemagg@yahoo.com 13 // http://www.antigrain.com 14 //---------------------------------------------------------------------------- 15 16 #ifndef AGG_SCANLINE_STORAGE_BIN_INCLUDED 17 #define AGG_SCANLINE_STORAGE_BIN_INCLUDED 18 19 #include <string.h> 20 #include <stdlib.h> 21 #include <math.h> 22 #include "agg_array.h" 23 #include "agg_render_scanlines.h" 24 25 26 namespace agg 27 { 28 29 //-----------------------------------------------scanline_storage_bin 30 class scanline_storage_bin 31 { 32 public: 33 //--------------------------------------------------------------- 34 struct span_data 35 { 36 int16 x; 37 int16 len; 38 }; 39 40 //--------------------------------------------------------------- 41 struct scanline_data 42 { 43 int y; 44 unsigned num_spans; 45 unsigned start_span; 46 }; 47 48 49 //--------------------------------------------------------------- 50 class embedded_scanline 51 { 52 public: 53 54 //----------------------------------------------------------- 55 class const_iterator 56 { 57 public: 58 const_iterator(const embedded_scanline& sl) : 59 m_storage(sl.m_storage), 60 m_span_idx(sl.m_scanline.start_span) 61 { 62 m_span = m_storage->span_by_index(m_span_idx); 63 } 64 65 const span_data& operator*() const { return m_span; } 66 const span_data* operator->() const { return &m_span; } 67 68 void operator ++ () 69 { 70 ++m_span_idx; 71 m_span = m_storage->span_by_index(m_span_idx); 72 } 73 74 private: 75 const scanline_storage_bin* m_storage; 76 unsigned m_span_idx; 77 span_data m_span; 78 }; 79 80 friend class const_iterator; 81 82 83 //----------------------------------------------------------- 84 embedded_scanline(const scanline_storage_bin& storage) : 85 m_storage(&storage) 86 { 87 setup(0); 88 } 89 90 //----------------------------------------------------------- 91 void reset(int, int) {} 92 unsigned num_spans() const { return m_scanline.num_spans; } 93 int y() const { return m_scanline.y; } 94 const_iterator begin() const { return const_iterator(*this); } 95 96 //----------------------------------------------------------- 97 void setup(unsigned scanline_idx) 98 { 99 m_scanline_idx = scanline_idx; 100 m_scanline = m_storage->scanline_by_index(m_scanline_idx); 101 } 102 103 private: 104 const scanline_storage_bin* m_storage; 105 scanline_data m_scanline; 106 unsigned m_scanline_idx; 107 }; 108 109 110 //--------------------------------------------------------------- 111 scanline_storage_bin() : 112 m_spans(256-2), // Block increment size 113 m_scanlines(), 114 m_min_x( 0x7FFFFFFF), 115 m_min_y( 0x7FFFFFFF), 116 m_max_x(-0x7FFFFFFF), 117 m_max_y(-0x7FFFFFFF), 118 m_cur_scanline(0) 119 { 120 m_fake_scanline.y = 0; 121 m_fake_scanline.num_spans = 0; 122 m_fake_scanline.start_span = 0; 123 m_fake_span.x = 0; 124 m_fake_span.len = 0; 125 } 126 127 // Renderer Interface 128 //--------------------------------------------------------------- 129 void prepare(unsigned) 130 { 131 m_scanlines.remove_all(); 132 m_spans.remove_all(); 133 m_min_x = 0x7FFFFFFF; 134 m_min_y = 0x7FFFFFFF; 135 m_max_x = -0x7FFFFFFF; 136 m_max_y = -0x7FFFFFFF; 137 m_cur_scanline = 0; 138 } 139 140 //--------------------------------------------------------------- 141 template<class Scanline> void render(const Scanline& sl) 142 { 143 scanline_data sl_this; 144 145 int y = sl.y(); 146 if(y < m_min_y) m_min_y = y; 147 if(y > m_max_y) m_max_y = y; 148 149 sl_this.y = y; 150 sl_this.num_spans = sl.num_spans(); 151 sl_this.start_span = m_spans.size(); 152 typename Scanline::const_iterator span_iterator = sl.begin(); 153 154 unsigned num_spans = sl_this.num_spans; 155 do 156 { 157 span_data sp; 158 sp.x = span_iterator->x; 159 sp.len = (int16)abs((int)(span_iterator->len)); 160 m_spans.add(sp); 161 int x1 = sp.x; 162 int x2 = sp.x + sp.len - 1; 163 if(x1 < m_min_x) m_min_x = x1; 164 if(x2 > m_max_x) m_max_x = x2; 165 ++span_iterator; 166 } 167 while(--num_spans); 168 m_scanlines.add(sl_this); 169 } 170 171 172 //--------------------------------------------------------------- 173 // Iterate scanlines interface 174 int min_x() const { return m_min_x; } 175 int min_y() const { return m_min_y; } 176 int max_x() const { return m_max_x; } 177 int max_y() const { return m_max_y; } 178 179 //--------------------------------------------------------------- 180 bool rewind_scanlines() 181 { 182 m_cur_scanline = 0; 183 return m_scanlines.size() > 0; 184 } 185 186 187 //--------------------------------------------------------------- 188 template<class Scanline> bool sweep_scanline(Scanline& sl) 189 { 190 sl.reset_spans(); 191 for(;;) 192 { 193 if(m_cur_scanline >= m_scanlines.size()) return false; 194 const scanline_data& sl_this = m_scanlines[m_cur_scanline]; 195 196 unsigned num_spans = sl_this.num_spans; 197 unsigned span_idx = sl_this.start_span; 198 do 199 { 200 const span_data& sp = m_spans[span_idx++]; 201 sl.add_span(sp.x, sp.len, cover_full); 202 } 203 while(--num_spans); 204 205 ++m_cur_scanline; 206 if(sl.num_spans()) 207 { 208 sl.finalize(sl_this.y); 209 break; 210 } 211 } 212 return true; 213 } 214 215 216 //--------------------------------------------------------------- 217 // Specialization for embedded_scanline 218 bool sweep_scanline(embedded_scanline& sl) 219 { 220 do 221 { 222 if(m_cur_scanline >= m_scanlines.size()) return false; 223 sl.setup(m_cur_scanline); 224 ++m_cur_scanline; 225 } 226 while(sl.num_spans() == 0); 227 return true; 228 } 229 230 231 //--------------------------------------------------------------- 232 unsigned byte_size() const 233 { 234 unsigned i; 235 unsigned size = sizeof(int16) * 4; // min_x, min_y, max_x, max_y 236 237 for(i = 0; i < m_scanlines.size(); ++i) 238 { 239 size += sizeof(int16) * 2 + // Y, num_spans 240 unsigned(m_scanlines[i].num_spans) * sizeof(int16) * 2; // X, span_len 241 } 242 return size; 243 } 244 245 246 //--------------------------------------------------------------- 247 static void write_int16(int8u* dst, int16 val) 248 { 249 dst[0] = ((const int8u*)&val)[0]; 250 dst[1] = ((const int8u*)&val)[1]; 251 } 252 253 254 //--------------------------------------------------------------- 255 void serialize(int8u* data) const 256 { 257 unsigned i; 258 259 write_int16(data, int16u(min_x())); // min_x 260 data += sizeof(int16u); 261 write_int16(data, int16u(min_y())); // min_y 262 data += sizeof(int16u); 263 write_int16(data, int16u(max_x())); // max_x 264 data += sizeof(int16u); 265 write_int16(data, int16u(max_y())); // max_y 266 data += sizeof(int16u); 267 268 for(i = 0; i < m_scanlines.size(); ++i) 269 { 270 const scanline_data& sl_this = m_scanlines[i]; 271 272 write_int16(data, int16(sl_this.y)); // Y 273 data += sizeof(int16); 274 275 write_int16(data, int16(sl_this.num_spans)); // num_spans 276 data += sizeof(int16); 277 278 unsigned num_spans = sl_this.num_spans; 279 unsigned span_idx = sl_this.start_span; 280 do 281 { 282 const span_data& sp = m_spans[span_idx++]; 283 284 write_int16(data, int16(sp.x)); // X 285 data += sizeof(int16); 286 287 write_int16(data, int16(sp.len)); // len 288 data += sizeof(int16); 289 } 290 while(--num_spans); 291 } 292 } 293 294 295 //--------------------------------------------------------------- 296 const scanline_data& scanline_by_index(unsigned i) const 297 { 298 return (i < m_scanlines.size()) ? m_scanlines[i] : m_fake_scanline; 299 } 300 301 //--------------------------------------------------------------- 302 const span_data& span_by_index(unsigned i) const 303 { 304 return (i < m_spans.size()) ? m_spans[i] : m_fake_span; 305 } 306 307 308 private: 309 pod_deque<span_data, 10> m_spans; 310 pod_deque<scanline_data, 8> m_scanlines; 311 span_data m_fake_span; 312 scanline_data m_fake_scanline; 313 int m_min_x; 314 int m_min_y; 315 int m_max_x; 316 int m_max_y; 317 unsigned m_cur_scanline; 318 }; 319 320 321 322 323 324 325 326 327 328 329 330 331 332 //---------------------------------------serialized_scanlines_adaptor_bin 333 class serialized_scanlines_adaptor_bin 334 { 335 public: 336 typedef bool cover_type; 337 338 //-------------------------------------------------------------------- 339 class embedded_scanline 340 { 341 public: 342 343 //---------------------------------------------------------------- 344 class const_iterator 345 { 346 public: 347 struct span 348 { 349 int16 x; 350 int16 len; 351 }; 352 353 const_iterator(const embedded_scanline& sl) : 354 m_ptr(sl.m_ptr), 355 m_dx(sl.m_dx) 356 { 357 m_span.x = read_int16() + m_dx; 358 m_span.len = read_int16(); 359 } 360 361 const span& operator*() const { return m_span; } 362 const span* operator->() const { return &m_span; } 363 364 void operator ++ () 365 { 366 m_span.x = read_int16() + m_dx; 367 m_span.len = read_int16(); 368 } 369 370 private: 371 int read_int16() 372 { 373 int16 val; 374 ((int8u*)&val)[0] = *m_ptr++; 375 ((int8u*)&val)[1] = *m_ptr++; 376 return val; 377 } 378 379 const int8u* m_ptr; 380 span m_span; 381 int m_dx; 382 }; 383 384 friend class const_iterator; 385 386 387 //---------------------------------------------------------------- 388 embedded_scanline() : m_ptr(0), m_y(0), m_num_spans(0) {} 389 390 //---------------------------------------------------------------- 391 void reset(int, int) {} 392 unsigned num_spans() const { return m_num_spans; } 393 int y() const { return m_y; } 394 const_iterator begin() const { return const_iterator(*this); } 395 396 397 private: 398 //---------------------------------------------------------------- 399 int read_int16() 400 { 401 int16 val; 402 ((int8u*)&val)[0] = *m_ptr++; 403 ((int8u*)&val)[1] = *m_ptr++; 404 return val; 405 } 406 407 public: 408 //---------------------------------------------------------------- 409 void init(const int8u* ptr, int dx, int dy) 410 { 411 m_ptr = ptr; 412 m_y = read_int16() + dy; 413 m_num_spans = unsigned(read_int16()); 414 m_dx = dx; 415 } 416 417 private: 418 const int8u* m_ptr; 419 int m_y; 420 unsigned m_num_spans; 421 int m_dx; 422 }; 423 424 425 426 public: 427 //-------------------------------------------------------------------- 428 serialized_scanlines_adaptor_bin() : 429 m_data(0), 430 m_end(0), 431 m_ptr(0), 432 m_dx(0), 433 m_dy(0), 434 m_min_x(0x7FFFFFFF), 435 m_min_y(0x7FFFFFFF), 436 m_max_x(-0x7FFFFFFF), 437 m_max_y(-0x7FFFFFFF) 438 {} 439 440 //-------------------------------------------------------------------- 441 serialized_scanlines_adaptor_bin(const int8u* data, unsigned size, 442 double dx, double dy) : 443 m_data(data), 444 m_end(data + size), 445 m_ptr(data), 446 m_dx(int(floor(dx + 0.5))), 447 m_dy(int(floor(dy + 0.5))), 448 m_min_x(0x7FFFFFFF), 449 m_min_y(0x7FFFFFFF), 450 m_max_x(-0x7FFFFFFF), 451 m_max_y(-0x7FFFFFFF) 452 {} 453 454 //-------------------------------------------------------------------- 455 void init(const int8u* data, unsigned size, double dx, double dy) 456 { 457 m_data = data; 458 m_end = data + size; 459 m_ptr = data; 460 m_dx = int(floor(dx + 0.5)); 461 m_dy = int(floor(dy + 0.5)); 462 m_min_x = 0x7FFFFFFF; 463 m_min_y = 0x7FFFFFFF; 464 m_max_x = -0x7FFFFFFF; 465 m_max_y = -0x7FFFFFFF; 466 } 467 468 private: 469 //-------------------------------------------------------------------- 470 int read_int16() 471 { 472 int16 val; 473 ((int8u*)&val)[0] = *m_ptr++; 474 ((int8u*)&val)[1] = *m_ptr++; 475 return val; 476 } 477 478 public: 479 // Iterate scanlines interface 480 //-------------------------------------------------------------------- 481 bool rewind_scanlines() 482 { 483 m_ptr = m_data; 484 if(m_ptr < m_end) 485 { 486 m_min_x = read_int16() + m_dx; 487 m_min_y = read_int16() + m_dy; 488 m_max_x = read_int16() + m_dx; 489 m_max_y = read_int16() + m_dy; 490 return true; 491 } 492 return false; 493 } 494 495 //-------------------------------------------------------------------- 496 int min_x() const { return m_min_x; } 497 int min_y() const { return m_min_y; } 498 int max_x() const { return m_max_x; } 499 int max_y() const { return m_max_y; } 500 501 //-------------------------------------------------------------------- 502 template<class Scanline> bool sweep_scanline(Scanline& sl) 503 { 504 sl.reset_spans(); 505 for(;;) 506 { 507 if(m_ptr >= m_end) return false; 508 509 int y = read_int16() + m_dy; 510 unsigned num_spans = read_int16(); 511 512 do 513 { 514 int x = read_int16() + m_dx; 515 int len = read_int16(); 516 517 if(len < 0) len = -len; 518 sl.add_span(x, unsigned(len), cover_full); 519 } 520 while(--num_spans); 521 522 if(sl.num_spans()) 523 { 524 sl.finalize(y); 525 break; 526 } 527 } 528 return true; 529 } 530 531 532 //-------------------------------------------------------------------- 533 // Specialization for embedded_scanline 534 bool sweep_scanline(embedded_scanline& sl) 535 { 536 do 537 { 538 if(m_ptr >= m_end) return false; 539 540 sl.init(m_ptr, m_dx, m_dy); 541 542 // Jump to the next scanline 543 //-------------------------- 544 read_int16(); // Y 545 int num_spans = read_int16(); // num_spans 546 m_ptr += num_spans * sizeof(int16) * 2; 547 } 548 while(sl.num_spans() == 0); 549 return true; 550 } 551 552 private: 553 const int8u* m_data; 554 const int8u* m_end; 555 const int8u* m_ptr; 556 int m_dx; 557 int m_dy; 558 int m_min_x; 559 int m_min_y; 560 int m_max_x; 561 int m_max_y; 562 }; 563 564 565 566 } 567 568 #endif 569 570