diff options
Diffstat (limited to 'src/libnr/nr-blit.cpp')
| -rw-r--r-- | src/libnr/nr-blit.cpp | 300 |
1 files changed, 300 insertions, 0 deletions
diff --git a/src/libnr/nr-blit.cpp b/src/libnr/nr-blit.cpp new file mode 100644 index 000000000..2a93bc9bd --- /dev/null +++ b/src/libnr/nr-blit.cpp @@ -0,0 +1,300 @@ +#define __NR_BLIT_C__ + +/* + * Pixel buffer rendering library + * + * Authors: + * Lauris Kaplinski <lauris@kaplinski.com> + * + * This code is in public domain + */ + +#include "nr-pixops.h" +#include "nr-compose.h" +#include "nr-blit.h" + +void +nr_blit_pixblock_pixblock_alpha (NRPixBlock *d, NRPixBlock *s, unsigned int alpha) +{ + NRRectL clip; + unsigned char *dpx, *spx; + int dbpp, sbpp; + int w, h; + + if (alpha == 0) return; + if (s->empty) return; + /* fixme: */ + if (s->mode == NR_PIXBLOCK_MODE_A8) return; + /* fixme: */ + if (s->mode == NR_PIXBLOCK_MODE_R8G8B8) return; + + /* + * Possible variants as of now: + * + * 0. SRC EP - DST EP * + * 1. SRC EP - DST EN * + * 2. SRC EP - DST P * + * 3. SRC EP - DST N * + * 4. SRC EN - DST EP * + * 5. SRC EN - DST EN * + * 6. SRC EN - DST P * + * 7. SRC EN - DST N * + * 8. SRC P - DST EP * + * 9. SRC P - DST EN * + * A. SRC P - DST P * + * B. SRC P - DST N * + * C. SRC N - DST EP * + * D. SRC N - DST EN * + * E. SRC N - DST P * + * F. SRC N - DST N * + * + */ + + nr_rect_l_intersect (&clip, &d->area, &s->area); + + if (nr_rect_l_test_empty (&clip)) return; + + /* Pointers */ + dbpp = NR_PIXBLOCK_BPP (d); + dpx = NR_PIXBLOCK_PX (d) + (clip.y0 - d->area.y0) * d->rs + dbpp * (clip.x0 - d->area.x0); + sbpp = NR_PIXBLOCK_BPP (s); + spx = NR_PIXBLOCK_PX (s) + (clip.y0 - s->area.y0) * s->rs + sbpp * (clip.x0 - s->area.x0); + w = clip.x1 - clip.x0; + h = clip.y1 - clip.y0; + + switch (d->mode) { + case NR_PIXBLOCK_MODE_A8: + /* No rendering into alpha at moment */ + break; + case NR_PIXBLOCK_MODE_R8G8B8: + if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) { + nr_R8G8B8_R8G8B8_R8G8B8A8_P (dpx, w, h, d->rs, spx, s->rs, alpha); + } else { + nr_R8G8B8_R8G8B8_R8G8B8A8_N (dpx, w, h, d->rs, spx, s->rs, alpha); + } + break; + case NR_PIXBLOCK_MODE_R8G8B8A8P: + if (d->empty) { + if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) { + /* Case 8 */ + nr_R8G8B8A8_P_EMPTY_R8G8B8A8_P (dpx, w, h, d->rs, spx, s->rs, alpha); + } else { + /* Case C */ + nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N (dpx, w, h, d->rs, spx, s->rs, alpha); + } + } else { + if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) { + /* case A */ + nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_P (dpx, w, h, d->rs, spx, s->rs, alpha); + } else { + /* case E */ + nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N (dpx, w, h, d->rs, spx, s->rs, alpha); + } + } + break; + case NR_PIXBLOCK_MODE_R8G8B8A8N: + if (d->empty) { + if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) { + /* Case 9 */ + nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P (dpx, w, h, d->rs, spx, s->rs, alpha); + } else { + /* Case D */ + nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N (dpx, w, h, d->rs, spx, s->rs, alpha); + } + } else { + if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) { + /* case B */ + nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P (dpx, w, h, d->rs, spx, s->rs, alpha); + } else { + /* case F */ + nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N (dpx, w, h, d->rs, spx, s->rs, alpha); + } + } + break; + } +} + +void +nr_blit_pixblock_pixblock_mask (NRPixBlock *d, NRPixBlock *s, NRPixBlock *m) +{ + NRRectL clip; + unsigned char *dpx, *spx, *mpx; + int dbpp, sbpp; + int w, h; + + if (s->empty) return; + /* fixme: */ + if (s->mode == NR_PIXBLOCK_MODE_A8) return; + /* fixme: */ + if (s->mode == NR_PIXBLOCK_MODE_R8G8B8) return; + + /* + * Possible variants as of now: + * + * 0. SRC EP - DST EP * + * 1. SRC EP - DST EN * + * 2. SRC EP - DST P * + * 3. SRC EP - DST N * + * 4. SRC EN - DST EP * + * 5. SRC EN - DST EN * + * 6. SRC EN - DST P * + * 7. SRC EN - DST N * + * 8. SRC P - DST EP * + * 9. SRC P - DST EN * + * A. SRC P - DST P * + * B. SRC P - DST N * + * C. SRC N - DST EP * + * D. SRC N - DST EN * + * E. SRC N - DST P * + * F. SRC N - DST N * + * + */ + + nr_rect_l_intersect (&clip, &d->area, &s->area); + nr_rect_l_intersect (&clip, &clip, &m->area); + + if (nr_rect_l_test_empty (&clip)) return; + + /* Pointers */ + dbpp = NR_PIXBLOCK_BPP (d); + dpx = NR_PIXBLOCK_PX (d) + (clip.y0 - d->area.y0) * d->rs + dbpp * (clip.x0 - d->area.x0); + sbpp = NR_PIXBLOCK_BPP (s); + spx = NR_PIXBLOCK_PX (s) + (clip.y0 - s->area.y0) * s->rs + sbpp * (clip.x0 - s->area.x0); + mpx = NR_PIXBLOCK_PX (m) + (clip.y0 - m->area.y0) * m->rs + 1 * (clip.x0 - m->area.x0); + w = clip.x1 - clip.x0; + h = clip.y1 - clip.y0; + + switch (d->mode) { + case NR_PIXBLOCK_MODE_A8: + /* No rendering into alpha at moment */ + break; + case NR_PIXBLOCK_MODE_R8G8B8: + if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) { + nr_R8G8B8_R8G8B8_R8G8B8A8_P_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs); + } else { + nr_R8G8B8_R8G8B8_R8G8B8A8_N_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs); + } + break; + case NR_PIXBLOCK_MODE_R8G8B8A8P: + if (d->empty) { + if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) { + /* Case 8 */ + nr_R8G8B8A8_P_EMPTY_R8G8B8A8_P_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs); + } else { + /* Case C */ + nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs); + } + } else { + if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) { + /* case A */ + nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_P_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs); + } else { + /* case E */ + nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs); + } + } + break; + case NR_PIXBLOCK_MODE_R8G8B8A8N: + if (d->empty) { + if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) { + /* Case 9 */ + nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs); + } else { + /* Case D */ + nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs); + } + } else { + if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) { + /* case B */ + nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs); + } else { + /* case F */ + nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs); + } + } + break; + } +} + +void +nr_blit_pixblock_mask_rgba32 (NRPixBlock *d, NRPixBlock *m, unsigned long rgba) +{ + if (!(rgba & 0xff)) return; + + if (m) { + NRRectL clip; + unsigned char *dpx, *mpx; + int w, h; + + if (m->mode != NR_PIXBLOCK_MODE_A8) return; + + if (!nr_rect_l_test_intersect (&d->area, &m->area)) return; + + nr_rect_l_intersect (&clip, &d->area, &m->area); + + /* Pointers */ + dpx = NR_PIXBLOCK_PX (d) + (clip.y0 - d->area.y0) * d->rs + NR_PIXBLOCK_BPP (d) * (clip.x0 - d->area.x0); + mpx = NR_PIXBLOCK_PX (m) + (clip.y0 - m->area.y0) * m->rs + (clip.x0 - m->area.x0); + w = clip.x1 - clip.x0; + h = clip.y1 - clip.y0; + + if (d->empty) { + if (d->mode == NR_PIXBLOCK_MODE_R8G8B8) { + nr_R8G8B8_R8G8B8_A8_RGBA32 (dpx, w, h, d->rs, mpx, m->rs, rgba); + } else if (d->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) { + nr_R8G8B8A8_P_EMPTY_A8_RGBA32 (dpx, w, h, d->rs, mpx, m->rs, rgba); + } else { + nr_R8G8B8A8_N_EMPTY_A8_RGBA32 (dpx, w, h, d->rs, mpx, m->rs, rgba); + } + d->empty = 0; + } else { + if (d->mode == NR_PIXBLOCK_MODE_R8G8B8) { + nr_R8G8B8_R8G8B8_A8_RGBA32 (dpx, w, h, d->rs, mpx, m->rs, rgba); + } else if (d->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) { + nr_R8G8B8A8_P_R8G8B8A8_P_A8_RGBA32 (dpx, w, h, d->rs, mpx, m->rs, rgba); + } else { + nr_R8G8B8A8_N_R8G8B8A8_N_A8_RGBA32 (dpx, w, h, d->rs, mpx, m->rs, rgba); + } + } + } else { + unsigned int r, g, b, a; + int x, y; + r = NR_RGBA32_R (rgba); + g = NR_RGBA32_G (rgba); + b = NR_RGBA32_B (rgba); + a = NR_RGBA32_A (rgba); + for (y = d->area.y0; y < d->area.y1; y++) { + unsigned char *p; + p = NR_PIXBLOCK_PX (d) + (y - d->area.y0) * d->rs; + for (x = d->area.x0; x < d->area.x1; x++) { + unsigned int da; + switch (d->mode) { + case NR_PIXBLOCK_MODE_R8G8B8: + p[0] = NR_COMPOSEN11 (r, a, p[0]); + p[1] = NR_COMPOSEN11 (g, a, p[1]); + p[2] = NR_COMPOSEN11 (b, a, p[2]); + p += 3; + break; + case NR_PIXBLOCK_MODE_R8G8B8A8P: + p[0] = NR_COMPOSENPP (r, a, p[0], p[3]); + p[1] = NR_COMPOSENPP (g, a, p[1], p[3]); + p[2] = NR_COMPOSENPP (b, a, p[2], p[3]); + p[3] = (65025 - (255 - a) * (255 - p[3]) + 127) / 255; + p += 4; + break; + case NR_PIXBLOCK_MODE_R8G8B8A8N: + da = 65025 - (255 - a) * (255 - p[3]); + p[0] = NR_COMPOSENNN_A7 (r, a, p[0], p[3], da); + p[1] = NR_COMPOSENNN_A7 (g, a, p[1], p[3], da); + p[2] = NR_COMPOSENNN_A7 (b, a, p[2], p[3], da); + p[3] = (da + 127) / 255; + p += 4; + break; + default: + break; + } + } + } + } +} + |
