1 /* 2 * Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>. 3 * All rights reserved. Distributed under the terms of the MIT License. 4 * 5 * Copyright 2002-2004 Maxim Shemanarev (http://www.antigrain.com) 6 * 7 * 8 * Class scanline_storage_subpix, a slightly modified version of 9 * scanline_storage customized to store 3 covers per pixel 10 * 11 */ 12 13 #ifndef AGG_SCANLINE_STORAGE_SUBPIX_INCLUDED 14 #define AGG_SCANLINE_STORAGE_SUBPIX_INCLUDED 15 16 #include <string.h> 17 #include <stdlib.h> 18 #include <math.h> 19 #include "agg_array.h" 20 #include "agg_scanline_storage_aa.h" 21 22 23 namespace agg 24 { 25 //--------------------------------------------scanline_storage_subpix 26 template<class T> class scanline_storage_subpix 27 { 28 public: 29 typedef T cover_type; 30 31 //--------------------------------------------------------------- 32 struct span_data 33 { 34 int32 x; 35 int32 len; // If negative, it's a solid span, covers is valid 36 int covers_id; // The index of the cells in the scanline_cell_storage 37 }; 38 39 //--------------------------------------------------------------- 40 struct scanline_data 41 { 42 int y; 43 unsigned num_spans; 44 unsigned start_span; 45 }; 46 47 48 //--------------------------------------------------------------- 49 class embedded_scanline 50 { 51 public: 52 53 //----------------------------------------------------------- 54 class const_iterator 55 { 56 public: 57 struct span 58 { 59 int32 x; 60 int32 len; // If negative, it's a solid span, covers is valid 61 const T* covers; 62 }; 63 const_iterator()64 const_iterator() : m_storage(0) {} const_iterator(const embedded_scanline & sl)65 const_iterator(const embedded_scanline& sl) : 66 m_storage(sl.m_storage), 67 m_span_idx(sl.m_scanline.start_span) 68 { 69 init_span(); 70 } 71 72 const span& operator*() const { return m_span; } 73 const span* operator->() const { return &m_span; } 74 75 void operator ++ () 76 { 77 ++m_span_idx; 78 init_span(); 79 } 80 81 private: init_span()82 void init_span() 83 { 84 const span_data& s = m_storage->span_by_index(m_span_idx); 85 m_span.x = s.x; 86 m_span.len = s.len; 87 m_span.covers = m_storage->covers_by_index(s.covers_id); 88 } 89 90 const scanline_storage_subpix* m_storage; 91 unsigned m_span_idx; 92 span m_span; 93 }; 94 95 friend class const_iterator; 96 97 98 //----------------------------------------------------------- embedded_scanline(const scanline_storage_subpix & storage)99 embedded_scanline(const scanline_storage_subpix& storage) : 100 m_storage(&storage) 101 { 102 init(0); 103 } 104 105 //----------------------------------------------------------- reset(int,int)106 void reset(int, int) {} num_spans()107 unsigned num_spans() const { return m_scanline.num_spans; } y()108 int y() const { return m_scanline.y; } begin()109 const_iterator begin() const { return const_iterator(*this); } 110 111 //----------------------------------------------------------- init(unsigned scanline_idx)112 void init(unsigned scanline_idx) 113 { 114 m_scanline_idx = scanline_idx; 115 m_scanline = m_storage->scanline_by_index(m_scanline_idx); 116 } 117 118 private: 119 const scanline_storage_subpix* m_storage; 120 scanline_data m_scanline; 121 unsigned m_scanline_idx; 122 }; 123 124 125 //--------------------------------------------------------------- scanline_storage_subpix()126 scanline_storage_subpix() : 127 m_covers(), 128 m_spans(256-2), // Block increment size 129 m_scanlines(), 130 m_min_x( 0x7FFFFFFF), 131 m_min_y( 0x7FFFFFFF), 132 m_max_x(-0x7FFFFFFF), 133 m_max_y(-0x7FFFFFFF), 134 m_cur_scanline(0) 135 { 136 m_fake_scanline.y = 0; 137 m_fake_scanline.num_spans = 0; 138 m_fake_scanline.start_span = 0; 139 m_fake_span.x = 0; 140 m_fake_span.len = 0; 141 m_fake_span.covers_id = 0; 142 } 143 144 // Renderer Interface 145 //--------------------------------------------------------------- prepare()146 void prepare() 147 { 148 m_covers.remove_all(); 149 m_scanlines.remove_all(); 150 m_spans.remove_all(); 151 m_min_x = 0x7FFFFFFF; 152 m_min_y = 0x7FFFFFFF; 153 m_max_x = -0x7FFFFFFF; 154 m_max_y = -0x7FFFFFFF; 155 m_cur_scanline = 0; 156 } 157 158 //--------------------------------------------------------------- render(const Scanline & sl)159 template<class Scanline> void render(const Scanline& sl) 160 { 161 scanline_data sl_this; 162 163 int y = sl.y(); 164 if(y < m_min_y) m_min_y = y; 165 if(y > m_max_y) m_max_y = y; 166 167 sl_this.y = y; 168 sl_this.num_spans = sl.num_spans(); 169 sl_this.start_span = m_spans.size(); 170 typename Scanline::const_iterator span_iterator = sl.begin(); 171 172 unsigned num_spans = sl_this.num_spans; 173 for(;;) 174 { 175 span_data sp; 176 177 sp.x = span_iterator->x; 178 sp.len = span_iterator->len; 179 int len = abs(int(sp.len)); 180 sp.covers_id = 181 m_covers.add_cells(span_iterator->covers, 182 (unsigned(len))); 183 m_spans.add(sp); 184 int x1 = sp.x; 185 int x2 = sp.x + len/3 - 1; 186 if(x1 < m_min_x) m_min_x = x1; 187 if(x2 > m_max_x) m_max_x = x2; 188 if(--num_spans == 0) break; 189 ++span_iterator; 190 } 191 m_scanlines.add(sl_this); 192 } 193 194 195 //--------------------------------------------------------------- 196 // Iterate scanlines interface min_x()197 int min_x() const { return m_min_x; } min_y()198 int min_y() const { return m_min_y; } max_x()199 int max_x() const { return m_max_x; } max_y()200 int max_y() const { return m_max_y; } 201 202 //--------------------------------------------------------------- rewind_scanlines()203 bool rewind_scanlines() 204 { 205 m_cur_scanline = 0; 206 return m_scanlines.size() > 0; 207 } 208 209 210 //--------------------------------------------------------------- sweep_scanline(Scanline & sl)211 template<class Scanline> bool sweep_scanline(Scanline& sl) 212 { 213 sl.reset_spans(); 214 for(;;) 215 { 216 if(m_cur_scanline >= m_scanlines.size()) return false; 217 const scanline_data& sl_this = m_scanlines[m_cur_scanline]; 218 219 unsigned num_spans = sl_this.num_spans; 220 unsigned span_idx = sl_this.start_span; 221 do 222 { 223 const span_data& sp = m_spans[span_idx++]; 224 const T* covers = covers_by_index(sp.covers_id); 225 if(sp.len < 0) 226 { 227 sl.add_span(sp.x, unsigned(-sp.len), *covers); 228 } 229 else 230 { 231 sl.add_cells(sp.x, sp.len, covers); 232 } 233 } 234 while(--num_spans); 235 ++m_cur_scanline; 236 if(sl.num_spans()) 237 { 238 sl.finalize(sl_this.y); 239 break; 240 } 241 } 242 return true; 243 } 244 245 246 //--------------------------------------------------------------- 247 // Specialization for embedded_scanline sweep_scanline(embedded_scanline & sl)248 bool sweep_scanline(embedded_scanline& sl) 249 { 250 do 251 { 252 if(m_cur_scanline >= m_scanlines.size()) return false; 253 sl.init(m_cur_scanline); 254 ++m_cur_scanline; 255 } 256 while(sl.num_spans() == 0); 257 return true; 258 } 259 260 //--------------------------------------------------------------- byte_size()261 unsigned byte_size() const 262 { 263 unsigned i; 264 unsigned size = sizeof(int32) * 4; // min_x, min_y, max_x, max_y 265 266 for(i = 0; i < m_scanlines.size(); ++i) 267 { 268 size += sizeof(int32) * 3; // scanline size in bytes 269 270 const scanline_data& sl_this = m_scanlines[i]; 271 272 unsigned num_spans = sl_this.num_spans; 273 unsigned span_idx = sl_this.start_span; 274 do 275 { 276 const span_data& sp = m_spans[span_idx++]; 277 278 size += sizeof(int32) * 2; // X, span_len 279 if(sp.len < 0) 280 { 281 size += sizeof(T); // cover 282 } 283 else 284 { 285 size += sizeof(T) * unsigned(sp.len); // covers 286 } 287 } 288 while(--num_spans); 289 } 290 return size; 291 } 292 293 294 //--------------------------------------------------------------- write_int32(int8u * dst,int32 val)295 static void write_int32(int8u* dst, int32 val) 296 { 297 dst[0] = ((const int8u*)&val)[0]; 298 dst[1] = ((const int8u*)&val)[1]; 299 dst[2] = ((const int8u*)&val)[2]; 300 dst[3] = ((const int8u*)&val)[3]; 301 } 302 303 304 //--------------------------------------------------------------- serialize(int8u * data)305 void serialize(int8u* data) const 306 { 307 unsigned i; 308 309 write_int32(data, min_x()); // min_x 310 data += sizeof(int32); 311 write_int32(data, min_y()); // min_y 312 data += sizeof(int32); 313 write_int32(data, max_x()); // max_x 314 data += sizeof(int32); 315 write_int32(data, max_y()); // max_y 316 data += sizeof(int32); 317 318 for(i = 0; i < m_scanlines.size(); ++i) 319 { 320 const scanline_data& sl_this = m_scanlines[i]; 321 322 int8u* size_ptr = data; 323 data += sizeof(int32); // Reserve space for scanline size in bytes 324 325 write_int32(data, sl_this.y); // Y 326 data += sizeof(int32); 327 328 write_int32(data, sl_this.num_spans); // num_spans 329 data += sizeof(int32); 330 331 unsigned num_spans = sl_this.num_spans; 332 unsigned span_idx = sl_this.start_span; 333 do 334 { 335 const span_data& sp = m_spans[span_idx++]; 336 const T* covers = covers_by_index(sp.covers_id); 337 338 write_int32(data, sp.x); // X 339 data += sizeof(int32); 340 341 write_int32(data, sp.len); // span_len 342 data += sizeof(int32); 343 344 if(sp.len < 0) 345 { 346 memcpy(data, covers, sizeof(T)); 347 data += sizeof(T); 348 } 349 else 350 { 351 memcpy(data, covers, unsigned(sp.len) * sizeof(T)); 352 data += sizeof(T) * unsigned(sp.len); 353 } 354 } 355 while(--num_spans); 356 write_int32(size_ptr, int32(unsigned(data - size_ptr))); 357 } 358 } 359 360 361 //--------------------------------------------------------------- scanline_by_index(unsigned i)362 const scanline_data& scanline_by_index(unsigned i) const 363 { 364 return (i < m_scanlines.size()) ? m_scanlines[i] : m_fake_scanline; 365 } 366 367 //--------------------------------------------------------------- span_by_index(unsigned i)368 const span_data& span_by_index(unsigned i) const 369 { 370 return (i < m_spans.size()) ? m_spans[i] : m_fake_span; 371 } 372 373 //--------------------------------------------------------------- covers_by_index(int i)374 const T* covers_by_index(int i) const 375 { 376 return m_covers[i]; 377 } 378 379 private: 380 scanline_cell_storage<T> m_covers; 381 pod_bvector<span_data, 10> m_spans; 382 pod_bvector<scanline_data, 8> m_scanlines; 383 span_data m_fake_span; 384 scanline_data m_fake_scanline; 385 int m_min_x; 386 int m_min_y; 387 int m_max_x; 388 int m_max_y; 389 unsigned m_cur_scanline; 390 }; 391 392 393 typedef scanline_storage_subpix<int8u> scanline_storage_subpix8; //--------scanline_storage_subpix8 394 typedef scanline_storage_subpix<int16u> scanline_storage_subpix16; //--------scanline_storage_subpix16 395 typedef scanline_storage_subpix<int32u> scanline_storage_subpix32; //--------scanline_storage_subpix32 396 397 398 //--------------------------------------serialized_scanlines_adaptor_subpix 399 template<class T> class serialized_scanlines_adaptor_subpix 400 { 401 public: 402 typedef T cover_type; 403 404 //--------------------------------------------------------------------- 405 class embedded_scanline 406 { 407 public: 408 typedef T cover_type; 409 410 //----------------------------------------------------------------- 411 class const_iterator 412 { 413 public: 414 struct span 415 { 416 int32 x; 417 int32 len; // If negative, it's a solid span, "covers" is valid 418 const T* covers; 419 }; 420 const_iterator()421 const_iterator() : m_ptr(0) {} const_iterator(const embedded_scanline & sl)422 const_iterator(const embedded_scanline& sl) : 423 m_ptr(sl.m_ptr), 424 m_dx(sl.m_dx) 425 { 426 init_span(); 427 } 428 429 const span& operator*() const { return m_span; } 430 const span* operator->() const { return &m_span; } 431 432 void operator ++ () 433 { 434 if(m_span.len < 0) 435 { 436 m_ptr += sizeof(T); 437 } 438 else 439 { 440 m_ptr += m_span.len * sizeof(T); 441 } 442 init_span(); 443 } 444 445 private: read_int32()446 int read_int32() 447 { 448 int32 val; 449 ((int8u*)&val)[0] = *m_ptr++; 450 ((int8u*)&val)[1] = *m_ptr++; 451 ((int8u*)&val)[2] = *m_ptr++; 452 ((int8u*)&val)[3] = *m_ptr++; 453 return val; 454 } 455 init_span()456 void init_span() 457 { 458 m_span.x = read_int32() + m_dx; 459 m_span.len = read_int32(); 460 m_span.covers = m_ptr; 461 } 462 463 const int8u* m_ptr; 464 span m_span; 465 int m_dx; 466 }; 467 468 friend class const_iterator; 469 470 471 //----------------------------------------------------------------- embedded_scanline()472 embedded_scanline() : m_ptr(0), m_y(0), m_num_spans(0) {} 473 474 //----------------------------------------------------------------- reset(int,int)475 void reset(int, int) {} num_spans()476 unsigned num_spans() const { return m_num_spans; } y()477 int y() const { return m_y; } begin()478 const_iterator begin() const { return const_iterator(*this); } 479 480 481 private: 482 //----------------------------------------------------------------- read_int32()483 int read_int32() 484 { 485 int32 val; 486 ((int8u*)&val)[0] = *m_ptr++; 487 ((int8u*)&val)[1] = *m_ptr++; 488 ((int8u*)&val)[2] = *m_ptr++; 489 ((int8u*)&val)[3] = *m_ptr++; 490 return val; 491 } 492 493 public: 494 //----------------------------------------------------------------- init(const int8u * ptr,int dx,int dy)495 void init(const int8u* ptr, int dx, int dy) 496 { 497 m_ptr = ptr; 498 m_y = read_int32() + dy; 499 m_num_spans = unsigned(read_int32()); 500 m_dx = dx; 501 } 502 503 private: 504 const int8u* m_ptr; 505 int m_y; 506 unsigned m_num_spans; 507 int m_dx; 508 }; 509 510 511 512 public: 513 //-------------------------------------------------------------------- serialized_scanlines_adaptor_subpix()514 serialized_scanlines_adaptor_subpix() : 515 m_data(0), 516 m_end(0), 517 m_ptr(0), 518 m_dx(0), 519 m_dy(0), 520 m_min_x(0x7FFFFFFF), 521 m_min_y(0x7FFFFFFF), 522 m_max_x(-0x7FFFFFFF), 523 m_max_y(-0x7FFFFFFF) 524 {} 525 526 //-------------------------------------------------------------------- serialized_scanlines_adaptor_subpix(const int8u * data,unsigned size,double dx,double dy)527 serialized_scanlines_adaptor_subpix(const int8u* data, unsigned size, 528 double dx, double dy) : 529 m_data(data), 530 m_end(data + size), 531 m_ptr(data), 532 m_dx(iround(dx)), 533 m_dy(iround(dy)), 534 m_min_x(0x7FFFFFFF), 535 m_min_y(0x7FFFFFFF), 536 m_max_x(-0x7FFFFFFF), 537 m_max_y(-0x7FFFFFFF) 538 {} 539 540 //-------------------------------------------------------------------- init(const int8u * data,unsigned size,double dx,double dy)541 void init(const int8u* data, unsigned size, double dx, double dy) 542 { 543 m_data = data; 544 m_end = data + size; 545 m_ptr = data; 546 m_dx = iround(dx); 547 m_dy = iround(dy); 548 m_min_x = 0x7FFFFFFF; 549 m_min_y = 0x7FFFFFFF; 550 m_max_x = -0x7FFFFFFF; 551 m_max_y = -0x7FFFFFFF; 552 } 553 554 private: 555 //-------------------------------------------------------------------- read_int32()556 int read_int32() 557 { 558 int32 val; 559 ((int8u*)&val)[0] = *m_ptr++; 560 ((int8u*)&val)[1] = *m_ptr++; 561 ((int8u*)&val)[2] = *m_ptr++; 562 ((int8u*)&val)[3] = *m_ptr++; 563 return val; 564 } 565 566 //-------------------------------------------------------------------- read_int32u()567 unsigned read_int32u() 568 { 569 int32u val; 570 ((int8u*)&val)[0] = *m_ptr++; 571 ((int8u*)&val)[1] = *m_ptr++; 572 ((int8u*)&val)[2] = *m_ptr++; 573 ((int8u*)&val)[3] = *m_ptr++; 574 return val; 575 } 576 577 public: 578 // Iterate scanlines interface 579 //-------------------------------------------------------------------- rewind_scanlines()580 bool rewind_scanlines() 581 { 582 m_ptr = m_data; 583 if(m_ptr < m_end) 584 { 585 m_min_x = read_int32() + m_dx; 586 m_min_y = read_int32() + m_dy; 587 m_max_x = read_int32() + m_dx; 588 m_max_y = read_int32() + m_dy; 589 } 590 return m_ptr < m_end; 591 } 592 593 //-------------------------------------------------------------------- min_x()594 int min_x() const { return m_min_x; } min_y()595 int min_y() const { return m_min_y; } max_x()596 int max_x() const { return m_max_x; } max_y()597 int max_y() const { return m_max_y; } 598 599 //-------------------------------------------------------------------- sweep_scanline(Scanline & sl)600 template<class Scanline> bool sweep_scanline(Scanline& sl) 601 { 602 sl.reset_spans(); 603 for(;;) 604 { 605 if(m_ptr >= m_end) return false; 606 607 read_int32(); // Skip scanline size in bytes 608 int y = read_int32() + m_dy; 609 unsigned num_spans = read_int32(); 610 611 do 612 { 613 int x = read_int32() + m_dx; 614 int len = read_int32(); 615 616 if(len < 0) 617 { 618 sl.add_span(x, unsigned(-len), *m_ptr); 619 m_ptr += sizeof(T); 620 } 621 else 622 { 623 sl.add_cells(x, len, m_ptr); 624 m_ptr += len * sizeof(T); 625 } 626 } 627 while(--num_spans); 628 629 if(sl.num_spans()) 630 { 631 sl.finalize(y); 632 break; 633 } 634 } 635 return true; 636 } 637 638 639 //-------------------------------------------------------------------- 640 // Specialization for embedded_scanline sweep_scanline(embedded_scanline & sl)641 bool sweep_scanline(embedded_scanline& sl) 642 { 643 do 644 { 645 if(m_ptr >= m_end) return false; 646 647 unsigned byte_size = read_int32u(); 648 sl.init(m_ptr, m_dx, m_dy); 649 m_ptr += byte_size - sizeof(int32); 650 } 651 while(sl.num_spans() == 0); 652 return true; 653 } 654 655 private: 656 const int8u* m_data; 657 const int8u* m_end; 658 const int8u* m_ptr; 659 int m_dx; 660 int m_dy; 661 int m_min_x; 662 int m_min_y; 663 int m_max_x; 664 int m_max_y; 665 }; 666 667 668 669 typedef serialized_scanlines_adaptor_subpix<int8u> 670 serialized_scanlines_adaptor_subpix8; //serialized_scanlines_adaptor_subpix8 671 672 typedef serialized_scanlines_adaptor_subpix<int16u> 673 serialized_scanlines_adaptor_subpix16; //serialized_scanlines_adaptor_subpix16 674 675 typedef serialized_scanlines_adaptor_subpix<int32u> 676 serialized_scanlines_adaptor_subpix32; //serialized_scanlines_adaptor_subpix32 677 678 } 679 680 681 #endif 682 683