00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef AGG_RENDERER_BASE_INCLUDED
00021 #define AGG_RENDERER_BASE_INCLUDED
00022
00023 #include "agg_basics.h"
00024 #include "agg_rendering_buffer.h"
00025
00026 namespace agg
00027 {
00028
00029
00030 template<class PixelFormat> class renderer_base
00031 {
00032 public:
00033 typedef PixelFormat pixfmt_type;
00034 typedef typename pixfmt_type::color_type color_type;
00035
00036
00037 renderer_base(pixfmt_type& ren) :
00038 m_ren(&ren),
00039 m_clip_box(0, 0, ren.width() - 1, ren.height() - 1)
00040 {
00041 }
00042
00043
00044 const pixfmt_type& ren() const { return *m_ren; }
00045 pixfmt_type& ren() { return *m_ren; }
00046
00047
00048 unsigned width() const { return m_ren->width(); }
00049 unsigned height() const { return m_ren->height(); }
00050
00051
00052 bool clip_box(int x1, int y1, int x2, int y2)
00053 {
00054 rect cb(x1, y1, x2, y2);
00055 cb.normalize();
00056 if(cb.clip(rect(0, 0, width() - 1, height() - 1)))
00057 {
00058 m_clip_box = cb;
00059 return true;
00060 }
00061 m_clip_box.x1 = 1;
00062 m_clip_box.y1 = 1;
00063 m_clip_box.x2 = 0;
00064 m_clip_box.y2 = 0;
00065 return false;
00066 }
00067
00068
00069 void reset_clipping(bool visibility)
00070 {
00071 if(visibility)
00072 {
00073 m_clip_box.x1 = 0;
00074 m_clip_box.y1 = 0;
00075 m_clip_box.x2 = width() - 1;
00076 m_clip_box.y2 = height() - 1;
00077 }
00078 else
00079 {
00080 m_clip_box.x1 = 1;
00081 m_clip_box.y1 = 1;
00082 m_clip_box.x2 = 0;
00083 m_clip_box.y2 = 0;
00084 }
00085 }
00086
00087
00088 void clip_box_naked(int x1, int y1, int x2, int y2)
00089 {
00090 m_clip_box.x1 = x1;
00091 m_clip_box.y1 = y1;
00092 m_clip_box.x2 = x2;
00093 m_clip_box.y2 = y2;
00094 }
00095
00096
00097 bool inbox(int x, int y) const
00098 {
00099 return x >= m_clip_box.x1 && y >= m_clip_box.y1 &&
00100 x <= m_clip_box.x2 && y <= m_clip_box.y2;
00101 }
00102
00103
00104 void first_clip_box() {}
00105 bool next_clip_box() { return false; }
00106
00107
00108 const rect& clip_box() const { return m_clip_box; }
00109 int xmin() const { return m_clip_box.x1; }
00110 int ymin() const { return m_clip_box.y1; }
00111 int xmax() const { return m_clip_box.x2; }
00112 int ymax() const { return m_clip_box.y2; }
00113
00114
00115 const rect& bounding_clip_box() const { return m_clip_box; }
00116 int bounding_xmin() const { return m_clip_box.x1; }
00117 int bounding_ymin() const { return m_clip_box.y1; }
00118 int bounding_xmax() const { return m_clip_box.x2; }
00119 int bounding_ymax() const { return m_clip_box.y2; }
00120
00121
00122 void clear(const color_type& c)
00123 {
00124 unsigned y;
00125 if(width())
00126 {
00127 for(y = 0; y < height(); y++)
00128 {
00129 m_ren->copy_hline(0, y, width(), c);
00130 }
00131 }
00132 }
00133
00134
00135 void copy_pixel(int x, int y, const color_type& c)
00136 {
00137 if(inbox(x, y))
00138 {
00139 m_ren->copy_pixel(x, y, c);
00140 }
00141 }
00142
00143
00144 void blend_pixel(int x, int y, const color_type& c, cover_type cover)
00145 {
00146 if(inbox(x, y))
00147 {
00148 m_ren->blend_pixel(x, y, c, cover);
00149 }
00150 }
00151
00152
00153 color_type pixel(int x, int y) const
00154 {
00155 return inbox(x, y) ?
00156 m_ren->pixel(x, y) :
00157 color_type::no_color();
00158 }
00159
00160
00161 void copy_hline(int x1, int y, int x2, const color_type& c)
00162 {
00163 if(x1 > x2) { int t = x2; x2 = x1; x1 = t; }
00164 if(y > ymax()) return;
00165 if(y < ymin()) return;
00166 if(x1 > xmax()) return;
00167 if(x2 < xmin()) return;
00168
00169 if(x1 < xmin()) x1 = xmin();
00170 if(x2 > xmax()) x2 = xmax();
00171
00172 m_ren->copy_hline(x1, y, x2 - x1 + 1, c);
00173 }
00174
00175
00176 void copy_vline(int x, int y1, int y2, const color_type& c)
00177 {
00178 if(y1 > y2) { int t = y2; y2 = y1; y1 = t; }
00179 if(x > xmax()) return;
00180 if(x < xmin()) return;
00181 if(y1 > ymax()) return;
00182 if(y2 < ymin()) return;
00183
00184 if(y1 < ymin()) y1 = ymin();
00185 if(y2 > ymax()) y2 = ymax();
00186
00187 m_ren->copy_vline(x, y1, y2 - y1 + 1, c);
00188 }
00189
00190
00191 void blend_hline(int x1, int y, int x2,
00192 const color_type& c, cover_type cover)
00193 {
00194 if(x1 > x2) { int t = x2; x2 = x1; x1 = t; }
00195 if(y > ymax()) return;
00196 if(y < ymin()) return;
00197 if(x1 > xmax()) return;
00198 if(x2 < xmin()) return;
00199
00200 if(x1 < xmin()) x1 = xmin();
00201 if(x2 > xmax()) x2 = xmax();
00202
00203 m_ren->blend_hline(x1, y, x2 - x1 + 1, c, cover);
00204 }
00205
00206
00207 void blend_vline(int x, int y1, int y2,
00208 const color_type& c, cover_type cover)
00209 {
00210 if(y1 > y2) { int t = y2; y2 = y1; y1 = t; }
00211 if(x > xmax()) return;
00212 if(x < xmin()) return;
00213 if(y1 > ymax()) return;
00214 if(y2 < ymin()) return;
00215
00216 if(y1 < ymin()) y1 = ymin();
00217 if(y2 > ymax()) y2 = ymax();
00218
00219 m_ren->blend_vline(x, y1, y2 - y1 + 1, c, cover);
00220 }
00221
00222
00223
00224 void copy_bar(int x1, int y1, int x2, int y2, const color_type& c)
00225 {
00226 rect rc(x1, y1, x2, y2);
00227 rc.normalize();
00228 if(rc.clip(clip_box()))
00229 {
00230 int y;
00231 for(y = rc.y1; y <= rc.y2; y++)
00232 {
00233 m_ren->copy_hline(rc.x1, y, unsigned(rc.x2 - rc.x1 + 1), c);
00234 }
00235 }
00236 }
00237
00238
00239 void blend_bar(int x1, int y1, int x2, int y2,
00240 const color_type& c, cover_type cover)
00241 {
00242 rect rc(x1, y1, x2, y2);
00243 rc.normalize();
00244 if(rc.clip(clip_box()))
00245 {
00246 int y;
00247 for(y = rc.y1; y <= rc.y2; y++)
00248 {
00249 m_ren->blend_hline(rc.x1,
00250 y,
00251 unsigned(rc.x2 - rc.x1 + 1),
00252 c,
00253 cover);
00254 }
00255 }
00256 }
00257
00258
00259
00260 void blend_solid_hspan(int x, int y, int len,
00261 const color_type& c,
00262 const cover_type* covers)
00263 {
00264 if(y > ymax()) return;
00265 if(y < ymin()) return;
00266
00267 if(x < xmin())
00268 {
00269 len -= xmin() - x;
00270 if(len <= 0) return;
00271 covers += xmin() - x;
00272 x = xmin();
00273 }
00274 if(x + len > xmax())
00275 {
00276 len = xmax() - x + 1;
00277 if(len <= 0) return;
00278 }
00279 m_ren->blend_solid_hspan(x, y, len, c, covers);
00280 }
00281
00282
00283 void blend_solid_vspan(int x, int y, int len,
00284 const color_type& c,
00285 const cover_type* covers)
00286 {
00287 if(x > xmax()) return;
00288 if(x < xmin()) return;
00289
00290 if(y < ymin())
00291 {
00292 len -= ymin() - y;
00293 if(len <= 0) return;
00294 covers += ymin() - y;
00295 y = ymin();
00296 }
00297 if(y + len > ymax())
00298 {
00299 len = ymax() - y + 1;
00300 if(len <= 0) return;
00301 }
00302 m_ren->blend_solid_vspan(x, y, len, c, covers);
00303 }
00304
00305
00306 void blend_color_hspan(int x, int y, int len,
00307 const color_type* colors,
00308 const cover_type* covers,
00309 cover_type cover = cover_full)
00310 {
00311 if(y > ymax()) return;
00312 if(y < ymin()) return;
00313
00314 if(x < xmin())
00315 {
00316 int d = xmin() - x;
00317 len -= d;
00318 if(len <= 0) return;
00319 if(covers) covers += d;
00320 colors += d;
00321 x = xmin();
00322 }
00323 if(x + len > xmax())
00324 {
00325 len = xmax() - x + 1;
00326 if(len <= 0) return;
00327 }
00328 m_ren->blend_color_hspan(x, y, len, colors, covers, cover);
00329 }
00330
00331
00332 void blend_color_vspan(int x, int y, int len,
00333 const color_type* colors,
00334 const cover_type* covers,
00335 cover_type cover = cover_full)
00336 {
00337 if(x > xmax()) return;
00338 if(x < xmin()) return;
00339
00340 if(y < ymin())
00341 {
00342 int d = ymin() - y;
00343 len -= d;
00344 if(len <= 0) return;
00345 if(covers) covers += d;
00346 colors += d;
00347 y = ymin();
00348 }
00349 if(y + len > ymax())
00350 {
00351 len = ymax() - y + 1;
00352 if(len <= 0) return;
00353 }
00354 m_ren->blend_color_vspan(x, y, len, colors, covers, cover);
00355 }
00356
00357
00358 void blend_color_hspan_no_clip(int x, int y, int len,
00359 const color_type* colors,
00360 const cover_type* covers,
00361 cover_type cover = cover_full)
00362 {
00363 m_ren->blend_color_hspan(x, y, len, colors, covers, cover);
00364 }
00365
00366
00367 void blend_color_vspan_no_clip(int x, int y, int len,
00368 const color_type* colors,
00369 const cover_type* covers,
00370 cover_type cover = cover_full)
00371 {
00372 m_ren->blend_color_vspan(x, y, len, colors, covers, cover);
00373 }
00374
00375
00376
00377 rect clip_rect_area(rect& dst, rect& src, int wsrc, int hsrc) const
00378 {
00379 rect rc(0,0,0,0);
00380 rect cb = clip_box();
00381 ++cb.x2;
00382 ++cb.y2;
00383
00384 if(src.x1 < 0)
00385 {
00386 dst.x1 -= src.x1;
00387 src.x1 = 0;
00388 }
00389 if(src.y1 < 0)
00390 {
00391 dst.y1 -= src.y1;
00392 src.y1 = 0;
00393 }
00394
00395 if(src.x2 > wsrc) src.x2 = wsrc;
00396 if(src.y2 > hsrc) src.y2 = hsrc;
00397
00398 if(dst.x1 < cb.x1)
00399 {
00400 src.x1 += cb.x1 - dst.x1;
00401 dst.x1 = cb.x1;
00402 }
00403 if(dst.y1 < cb.y1)
00404 {
00405 src.y1 += cb.y1 - dst.y1;
00406 dst.y1 = cb.y1;
00407 }
00408
00409 if(dst.x2 > cb.x2) dst.x2 = cb.x2;
00410 if(dst.y2 > cb.y2) dst.y2 = cb.y2;
00411
00412 rc.x2 = dst.x2 - dst.x1;
00413 rc.y2 = dst.y2 - dst.y1;
00414
00415 if(rc.x2 > src.x2 - src.x1) rc.x2 = src.x2 - src.x1;
00416 if(rc.y2 > src.y2 - src.y1) rc.y2 = src.y2 - src.y1;
00417 return rc;
00418 }
00419
00420
00421
00422 void copy_from(const rendering_buffer& src,
00423 const rect* rect_src_ptr = 0,
00424 int dx = 0,
00425 int dy = 0)
00426 {
00427 rect rsrc(0, 0, src.width(), src.height());
00428 if(rect_src_ptr)
00429 {
00430 rsrc.x1 = rect_src_ptr->x1;
00431 rsrc.y1 = rect_src_ptr->y1;
00432 rsrc.x2 = rect_src_ptr->x2 + 1;
00433 rsrc.y2 = rect_src_ptr->y2 + 1;
00434 }
00435
00436
00437
00438
00439
00440 rect rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy);
00441
00442 rect rc = clip_rect_area(rdst, rsrc, src.width(), src.height());
00443
00444 if(rc.x2 > 0)
00445 {
00446 int incy = 1;
00447 if(rdst.y1 > rsrc.y1)
00448 {
00449 rsrc.y1 += rc.y2 - 1;
00450 rdst.y1 += rc.y2 - 1;
00451 incy = -1;
00452 }
00453 while(rc.y2 > 0)
00454 {
00455 m_ren->copy_from(src,
00456 rdst.x1, rdst.y1,
00457 rsrc.x1, rsrc.y1,
00458 rc.x2);
00459 rdst.y1 += incy;
00460 rsrc.y1 += incy;
00461 --rc.y2;
00462 }
00463 }
00464 }
00465
00466
00467
00468
00469 template<class SrcPixelFormatRenderer>
00470 void blend_from(const SrcPixelFormatRenderer& src,
00471 const rect* rect_src_ptr = 0,
00472 int dx = 0,
00473 int dy = 0)
00474 {
00475 rect rsrc(0, 0, src.width(), src.height());
00476 if(rect_src_ptr)
00477 {
00478 rsrc.x1 = rect_src_ptr->x1;
00479 rsrc.y1 = rect_src_ptr->y1;
00480 rsrc.x2 = rect_src_ptr->x2 + 1;
00481 rsrc.y2 = rect_src_ptr->y2 + 1;
00482 }
00483
00484
00485
00486
00487
00488 rect rdst(rsrc.x1 + dx, rsrc.y1 + dy, rsrc.x2 + dx, rsrc.y2 + dy);
00489
00490 rect rc = clip_rect_area(rdst, rsrc, src.width(), src.height());
00491
00492 if(rc.x2 > 0)
00493 {
00494 int incy = 1;
00495 if(rdst.y1 > rsrc.y1)
00496 {
00497 rsrc.y1 += rc.y2 - 1;
00498 rdst.y1 += rc.y2 - 1;
00499 incy = -1;
00500 }
00501 while(rc.y2 > 0)
00502 {
00503 typename SrcPixelFormatRenderer::row_data span = src.span(rsrc.x1, rsrc.y1);
00504 if(span.ptr)
00505 {
00506 int x1src = rsrc.x1;
00507 int x1dst = rdst.x1;
00508 int len = rc.x2;
00509 if(span.x1 > x1src)
00510 {
00511 x1dst += span.x1 - x1src;
00512 len -= span.x1 - x1src;
00513 x1src = span.x1;
00514 }
00515 if(len > 0)
00516 {
00517 if(x1src + len-1 > span.x2)
00518 {
00519 len -= x1src + len - span.x2 - 1;
00520 }
00521 if(len > 0)
00522 {
00523 m_ren->blend_from(src, span.ptr,
00524 x1dst, rdst.y1,
00525 x1src, rsrc.y1,
00526 len);
00527 }
00528 }
00529 }
00530 rdst.y1 += incy;
00531 rsrc.y1 += incy;
00532 --rc.y2;
00533 }
00534 }
00535 }
00536
00537
00538
00539 private:
00540 pixfmt_type* m_ren;
00541 rect m_clip_box;
00542 };
00543
00544
00545 }
00546
00547 #endif