YSTest  PreAlpha_b400_20130424
The YSLib Test Project
 全部  命名空间 文件 函数 变量 类型定义 枚举 枚举值 友元 宏定义  
yblit.h
浏览该文件的文档.
1 /*
2  Copyright by FrankHB 2009 - 2013.
3 
4  This file is part of the YSLib project, and may only be used,
5  modified, and distributed under the terms of the YSLib project
6  license, LICENSE.TXT. By continuing to use, modify, or distribute
7  this file you indicate that you have read the license and
8  understand and accept it fully.
9 */
10 
28 #ifndef YSL_INC_Service_yblit_h_
29 #define YSL_INC_Service_yblit_h_ 1
30 
31 #include "../Core/ygdibase.h"
32 #include "../Core/ycutil.h"
33 #include <ystdex/algorithm.hpp>
34 #include <ystdex/iterator.hpp>
35 
37 
38 YSL_BEGIN_NAMESPACE(Drawing)
39 
40 
44 typedef ystdex::pair_iterator<ConstBitmapPtr, const u8*> IteratorPair;
45 
50 typedef ystdex::pair_iterator<ystdex::pseudo_iterator<const PixelType>,
52 
53 
54 //基本仿函数。
55 
60 template<typename _tPixel>
62 {
63  _tPixel Color;
64 
68  explicit inline
69  PixelFiller(_tPixel c)
70  : Color(c)
71  {}
72 
76  inline void
77  operator()(_tPixel* dst)
78  {
79  *dst = Color;
80  }
81 };
82 
88 {
92  template<typename _tPixel, class _fTransformPixel>
93  void
94  operator()(_tPixel* dst, size_t n, _fTransformPixel tp)
95  {
96  if(YB_LIKELY(dst && n))
97  {
98  _tPixel* p(dst + n);
99 
100  while(--p >= dst)
101  tp(p);
102  }
103  }
104 };
105 
111 {
115  template<typename _tPixel, class _fTransformPixel>
116  void
117  operator()(_tPixel* dst, size_t n, SDst dw, _fTransformPixel tp)
118  {
119  if(YB_LIKELY(dst && n))
120  while(n--)
121  {
122  tp(dst);
123  dst += dw;
124  }
125  }
126 };
127 
128 
133 YF_API bool
134 BlitBounds(const Point& dp, const Point& sp,
135  const Size& ds, const Size& ss, const Size& cs,
136  int& min_x, int& min_y, int& delta_x, int& delta_y);
137 
143 template<bool _bSwapLR, bool _bSwapUD>
144 int
145 BlitScale(const Point& dp, const Size& ds, int delta_x, int delta_y);
146 template<>
147 YF_API int
148 BlitScale<false, false>(const Point&, const Size&, int, int);
149 template<>
150 YF_API int
151 BlitScale<true, false>(const Point&, const Size&, int, int);
152 template<>
153 YF_API int
154 BlitScale<false, true>(const Point&, const Size&, int, int);
155 template<>
156 YF_API int
157 BlitScale<true, true>(const Point&, const Size&, int, int);
159 
160 
180 template<bool _bDec, typename _fCallable, typename _tScalar, typename _tDiff,
181  typename _tOut, typename _tIn>
182 void
183 BlitScan(_fCallable&& f, _tScalar d_width, _tScalar s_width,
184  _tDiff delta_x, _tDiff delta_y, _tOut dst, _tIn src)
185 {
186  yforward(f)(delta_x, delta_y, dst, src,
187  (_bDec ? -1 : 1) * d_width - delta_x, s_width - delta_x);
188 }
189 
208 template<template<bool> class _gBlitLoop, bool _bSwapLR, bool _bSwapUD,
209  typename _tOut, typename _tIn>
210 void
211 Blit(_tOut dst, const Size& ds, _tIn src, const Size& ss,
212  const Point& dp, const Point& sp, const Size& sc)
213 {
214  int min_x, min_y, delta_x, delta_y;
215 
216  if(YB_LIKELY(BlitBounds(dp, sp, ds, ss, sc, min_x, min_y,
217  delta_x, delta_y)))
218  BlitScan<_bSwapLR != _bSwapUD>(_gBlitLoop<!_bSwapLR>(), ds.Width,
219  ss.Width, delta_x, delta_y, dst + BlitScale<_bSwapLR, _bSwapUD>(dp,
220  ds, delta_x, delta_y), src + (sp.Y + min_y) * ss.Width
221  + sp.X + min_x);
222 }
223 
224 
230 {
235  template<typename _tPixel, class _fTransformPixel, class _fTransformLine>
236  void
237  operator()(_tPixel* dst, const Size& ds, const Point& dp, const Size& ss,
238  _fTransformPixel tp, _fTransformLine tl)
239  {
240  int min_x, min_y, delta_x, delta_y;
241 
242  BlitBounds(dp, Point(), ds, ss, ss, min_x, min_y, delta_x, delta_y);
243  dst += max<SPos>(0, dp.Y) * ds.Width + max<SPos>(0, dp.X);
244  for(; delta_y > 0; --delta_y)
245  {
246  tl(dst, delta_x, tp);
247  dst += ds.Width;
248  }
249  }
254  template<typename _tPixel, class _fTransformPixel, class _fTransformLine>
255  inline void
256  operator()(_tPixel* dst, const Size& ds, const Rect& rSrc,
257  _fTransformPixel tp, _fTransformLine tl)
258  {
259  operator()<_tPixel, _fTransformPixel,
260  _fTransformLine>(dst, ds, rSrc.GetPoint(), rSrc.GetSize(), tp, tl);
261  }
266  template<typename _tPixel, class _fTransformPixel, class _fTransformLine>
267  inline void
268  operator()(_tPixel* dst, SDst dw, SDst dh, SPos dx, SPos dy,
269  SDst sw, SDst sh, _fTransformPixel tp, _fTransformLine tl)
270  {
271  operator()<_tPixel, _fTransformPixel, _fTransformLine>(
272  dst, Size(dw, dh), Point(dx, dy), Size(sw, sh), tp, tl);
273  }
274 };
275 
276 
277 //显示缓存操作:清除/以纯色像素填充。
278 
283 template<typename _tPixel>
284 inline _tPixel*
285 ClearPixel(_tPixel* dst, size_t n) ynothrow
286 {
287  ClearSequence(dst, n);
288  return dst;
289 }
290 
295 template<typename _tPixel>
296 inline void
297 FillPixel(_tPixel* dst, size_t n, _tPixel c)
298 {
300 }
301 
306 template<typename _tPixel>
307 inline void
308 FillVerticalLine(_tPixel* dst, size_t n, SDst dw, _tPixel c)
309 {
311 }
312 
317 template<typename _tPixel>
318 inline void
319 FillRect(_tPixel* dst, const Size& ds, const Point& sp, const Size& ss,
320  _tPixel c)
321 {
322  RectTransformer()(dst, ds, sp, ss, PixelFiller<_tPixel>(c),
324 }
329 template<typename _tPixel>
330 inline void
331 FillRect(_tPixel* dst, const Size& ds, const Rect& rSrc, _tPixel c)
332 {
333  RectTransformer()(dst, ds, rSrc, PixelFiller<_tPixel>(c),
335 }
340 template<typename _tPixel>
341 inline void
342 FillRect(_tPixel* dst, SDst dw, SDst dh, SPos sx, SPos sy, SDst sw, SDst sh,
343  _tPixel c)
344 {
345  RectTransformer()(dst, dw, dh, sx, sy, sw, sh, PixelFiller<_tPixel>(c),
347 }
348 
349 
350 //显示缓存操作:复制和贴图。
351 
358 template<bool _bPositiveScan>
359 void
360 BlitLine(BitmapPtr& dst_iter, ConstBitmapPtr& src_iter, int delta_x)
361 {
362  if(delta_x > 0)
363  {
364  std::copy_n(src_iter, delta_x, dst_iter);
365  src_iter += delta_x;
366  dst_iter += delta_x;
367  }
368 }
369 template<>
370 inline void
371 BlitLine<false>(BitmapPtr& dst_iter, ConstBitmapPtr& src_iter, int delta_x)
372 {
373  for(; delta_x > 0; --delta_x)
374  *dst_iter-- = *src_iter++;
375 }
377 
383 template<bool _bPositiveScan>
384 struct BlitLoop
385 {
386  void
387  operator()(int delta_x, int delta_y,
388  BitmapPtr dst_iter, ConstBitmapPtr src_iter,
389  int dst_inc, int src_inc)
390  {
391  for(; delta_y > 0; --delta_y)
392  {
393  BlitLine<_bPositiveScan>(dst_iter, src_iter, delta_x);
394  src_iter += src_inc;
395  ystdex::delta_assign<_bPositiveScan>(dst_iter, dst_inc);
396  }
397  }
398 };
399 
406 template<bool _bPositiveScan>
408 {
409  //使用源迭代器对应像素的第 15 位表示透明性。
410  void
411  operator()(int delta_x, int delta_y,
412  BitmapPtr dst_iter, ConstBitmapPtr src_iter,
413  int dst_inc, int src_inc)
414  {
415  for(; delta_y > 0; --delta_y)
416  {
417  for(int x(0); x < delta_x; ++x)
418  {
419  if(FetchAlpha(*src_iter))
420  *dst_iter = *src_iter;
421  ++src_iter;
422  ystdex::xcrease<_bPositiveScan>(dst_iter);
423  }
424  src_iter += src_inc;
425  ystdex::delta_assign<_bPositiveScan>(dst_iter, dst_inc);
426  }
427  }
428 
429  //使用 Alpha 通道表示透明性。
430  void
431  operator()(int delta_x, int delta_y,
432  BitmapPtr dst_iter, IteratorPair src_iter,
433  int dst_inc, int src_inc)
434  {
435  for(; delta_y > 0; --delta_y)
436  {
437  for(int x(0); x < delta_x; ++x)
438  {
439  *dst_iter = *src_iter.base().second & 0x80
440  ? FetchOpaque(*src_iter) : FetchOpaque(PixelType());
441  ++src_iter;
442  ystdex::xcrease<_bPositiveScan>(dst_iter);
443  }
444  src_iter += src_inc;
445  ystdex::delta_assign<_bPositiveScan>(dst_iter, dst_inc);
446  }
447  }
448 };
449 
450 
451 //#define YSL_FAST_BLIT
452 
453 #ifdef YSL_FAST_BLIT
454 
455 //测试用,不使用 Alpha 混合的快速算法。
456 
457 template<typename _tOut, typename _tIn>
458 void
459 biltAlphaPoint(_tOut dst_iter, _tIn src_iter);
460 template<>
461 inline void
462 biltAlphaPoint(PixelType* dst_iter, IteratorPair src_iter)
463 {
464  if(*src_iter.base().second >= BLT_THRESHOLD2)
465  *dst_iter = FetchOpaque(*src_iter);
466 }
467 template<>
468 inline void
469 biltAlphaPoint(PixelType* dst_iter, MonoIteratorPair src_iter)
470 {
471  if(*src_iter.base().second >= BLT_THRESHOLD2)
472  *dst_iter = FetchOpaque(*src_iter);
473 }
474 
475 #else
476 
483 
484 # ifdef YCL_PIXEL_FORMAT_AXYZ1555
485 
486 /*
487 \brief AXYZ1555 格式 PixelType 的 Alpha 混合。
488 \since build 189
489 
490 使用下列公式进行像素的 Alpha 混合(其中 alpha = a / BLT_MAX_ALPHA):
491 输出分量: dst := (1 - alpha) * d + alpha * s
492 = ((BLT_MAX_ALPHA - a) * d + a * s) >> BLT_ALPHA_BITS
493 = d + ((a * (s - d) + BLT_ROUND) >> BLT_ALPHA_BITS) 。
494 背景透明, 输出 Alpha 饱和。
495 */
496 inline u16
497 blitAlphaBlend(u32 d, u32 s, u8 a)
498 {
499  /*
500  格式: 16 位 AXYZ1555 ,以 ARGB1555 为例。
501  算法示意:
502  arrrrrgggggbbbbb
503  0000000000arrrrr gggggbbbbb000000
504  0000000000011111 0000000000011111
505  00000000000rrrrr 00000000000bbbbb : dbr
506  0000000000000000 000000ggggg00000 : dg
507  分解分量至 32 位寄存器以减少总指令数。
508  */
509  if(FetchAlpha(d) && a <= BLT_MAX_ALPHA - BLT_THRESHOLD)
510  {
511  u32 dbr((d & 0x1F) | (d << 6 & 0x1F0000)), dg(d & 0x3E0);
512 
513  dbr += ((((s & 0x1F) | (s << 6 & 0x1F0000)) - dbr) * a + BLT_ROUND_BR)
514  >> BLT_ALPHA_BITS,
515  dg += (((s & 0x3E0) - dg) * a + BLT_ROUND) >> BLT_ALPHA_BITS;
516  return FetchOpaque((dbr & 0x1F) | (dg & 0x3E0) | (dbr >> 6 & 0x7C00));
517  }
518  return a < BLT_THRESHOLD2 ? u16(d) : u16(FetchOpaque(s));
519 }
520 
521 # else
522 
523 /*
524 \brief Alpha 分量混合。
525 \since build 297
526 
527 输出分量: dst := (1 - alpha) * d + alpha * s
528 = ((BLT_MAX_ALPHA - a) * d + a * s) >> BLT_ALPHA_BITS
529 = d + ((a * (s - d) + BLT_ROUND) >> BLT_ALPHA_BITS) 。
530 */
531 inline u8
533 {
534  return d + ((a * (s - d) + BLT_ROUND) >> BLT_ALPHA_BITS);
535 }
536 
537 /*
538 \brief Alpha 混合。
539 \since build 297
540 
541 使用下列公式进行像素的 Alpha 混合(其中 alpha = a / BLT_MAX_ALPHA):
542 背景透明, 输出 Alpha 饱和。
543 */
544 inline PixelType
546 {
547  if(FetchAlpha(d) && a <= BLT_MAX_ALPHA - BLT_THRESHOLD)
548  {
549  const Color dc(d), sc(s);
550 
551  return Color(component_blend(dc.GetR(), sc.GetR(), a),
552  component_blend(dc.GetG(), sc.GetG(), a),
553  component_blend(dc.GetB(), sc.GetB(), a),
554  0xFF);
555  }
556  return a < BLT_THRESHOLD2 ? d : FetchOpaque(s);
557 }
558 
559 #endif
560 
561 template<typename _tOut, typename _tIn>
562 void
563 biltAlphaPoint(_tOut dst_iter, _tIn src_iter);
564 template<>
565 inline void
567 {
568  const u8 a(*src_iter.base().second);
569 
570  if(a >= BLT_THRESHOLD)
571  *dst_iter = blitAlphaBlend(*dst_iter, *src_iter, a);
572 }
573 template<>
574 inline void
575 biltAlphaPoint(PixelType* dst_iter, MonoIteratorPair src_iter)
576 {
577  const u8 a(*src_iter.base().second);
578 
579  if(a >= BLT_THRESHOLD)
580  *dst_iter = blitAlphaBlend(*dst_iter, *src_iter, a);
581 }
582 
583 #endif
584 
591 template<bool _bPositiveScan>
593 {
594  //使用 Alpha 通道表示 8 位透明度。
595  template<typename _tIn>
596  void
597  operator()(int delta_x, int delta_y,
598  BitmapPtr dst_iter, _tIn src_iter,
599  int dst_inc, int src_inc)
600  {
601  for(; delta_y > 0; --delta_y)
602  {
603  for(int x(0); x < delta_x; ++x)
604  {
605  biltAlphaPoint(dst_iter, src_iter);
606  ++src_iter;
607  ystdex::xcrease<_bPositiveScan>(dst_iter);
608  }
609  src_iter += src_inc;
610  ystdex::delta_assign<_bPositiveScan>(dst_iter, dst_inc);
611  }
612  }
613 };
614 
615 
620 template<class _fTransformPixel>
621 bool
622 TransformRect(const Graphics& g, const Point& pt, const Size& s,
623  _fTransformPixel tp)
624 {
625  if(YB_LIKELY(g))
626  {
627  RectTransformer()(g.GetBufferPtr(), g.GetSize(), pt, s, tp,
629  return true;
630  }
631  return false;
632 }
637 template<class _fTransformPixel>
638 inline bool
639 TransformRect(const Graphics& g, const Rect& r, _fTransformPixel tp)
640 {
641  return TransformRect<_fTransformPixel>(g, r.GetPoint(), r.GetSize(), tp);
642 }
643 
644 
651 YF_API void
652 CopyBuffer(const Graphics&, const Graphics&);
653 
658 YF_API void
659 ClearImage(const Graphics&);
660 
665 YF_API void
666 Fill(const Graphics&, Color);
667 
668 YSL_END_NAMESPACE(Drawing)
669 
670 YSL_END
671 
672 #endif
673