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