YSTest: yblit.h 源文件

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
36 YSL_BEGIN
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>,
51 const u8*> MonoIteratorPair;
52
53
54 //基本仿函数。
55
60 template<typename _tPixel>
61 struct PixelFiller
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
87 struct SequenceTransformer
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
110 struct VerticalLineTransfomer
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
229 struct RectTransformer
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 {
299 SequenceTransformer()(dst, n, PixelFiller<_tPixel>(c));
300 }
301
306 template<typename _tPixel>
307 inline void
308 FillVerticalLine(_tPixel* dst, size_t n, SDst dw, _tPixel c)
309 {
310 VerticalLineTransfomer()(dst, n, dw, PixelFiller<_tPixel>(c));
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),
323 SequenceTransformer());
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),
334 SequenceTransformer());
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),
346 SequenceTransformer());
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>
407 struct BlitTransparentLoop
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
477 yconstexpr u8 BLT_ALPHA_BITS(8);
478 yconstexpr u32 BLT_MAX_ALPHA((1 << BLT_ALPHA_BITS) - 1);
479 yconstexpr u32 BLT_ROUND(1 << (BLT_ALPHA_BITS - 1));
480 yconstexpr u8 BLT_THRESHOLD(8);
481 yconstexpr u8 BLT_THRESHOLD2(128);
482 yconstexpr u32 BLT_ROUND_BR(BLT_ROUND | BLT_ROUND << 16);
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
532 component_blend(u8 d, u8 s, u8 a)
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
545 blitAlphaBlend(PixelType d, PixelType s, u8 a)
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
566 biltAlphaPoint(PixelType* dst_iter, IteratorPair src_iter)
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>
592 struct BlitBlendLoop
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,
628 SequenceTransformer());
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