[sodipodi] [merge from sf] Added some blitting methods and image scaling/masking
- From: Hans Breuer <hans src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [sodipodi] [merge from sf] Added some blitting methods and image scaling/masking
- Date: Fri, 5 Oct 2012 18:18:59 +0000 (UTC)
commit cd50bfbdb4032c10c626a863be25f2e55b83370c
Author: Hans Breuer <hans breuer org>
Date: Fri Oct 5 19:50:00 2012 +0200
[merge from sf] Added some blitting methods and image scaling/masking
From: lauris <lauris 2490c5c0-b34c-4913-a0bd-69599dd9f015>
Date: Thu, 13 Oct 2011 23:23:32 +0000
git-svn-id: https://sodipodi.svn.sourceforge.net/svnroot/sodipodi/trunk 719 2490c5c0-b34c-4913-a0bd-69599dd9f015
From: lauris <lauris 2490c5c0-b34c-4913-a0bd-69599dd9f015>
Date: Fri, 23 Mar 2012 00:18:30 +0000
Subject: [PATCH 127/129] Added some G8 blitters
git-svn-id: https://sodipodi.svn.sourceforge.net/svnroot/sodipodi/trunk 728 2490c5c0-b34c-4913-a0bd-69599dd9f015
Plus preconditions;)
src/display/nr-arena-glyphs.c | 4 +-
src/display/nr-arena-item.c | 2 +-
src/display/nr-arena-shape.c | 4 +-
src/helper/nr-gradient-gpl.c | 6 +-
src/libnr/nr-blit.c | 97 +++++++++-----
src/libnr/nr-blit.h | 6 +-
src/libnr/nr-compose.c | 287 ++++++++++++++++++++++++++++++++++++++-
src/libnr/nr-compose.h | 28 +++--
src/libnr/nr-gradient.c | 4 +-
src/libnr/nr-pixblock-pattern.c | 4 +-
src/libnr/nr-pixblock-pixel.c | 20 ++--
src/libnr/nr-pixblock.c | 208 +++++++++++++++++++++++++---
src/libnr/nr-pixblock.h | 28 ++++-
src/libnr/nr-types.h | 2 +
src/libnr/testnr.c | 2 +-
src/libnrtype/nr-rasterfont.c | 4 +-
src/widgets/font-selector.c | 2 +-
17 files changed, 608 insertions(+), 100 deletions(-)
---
diff --git a/src/display/nr-arena-glyphs.c b/src/display/nr-arena-glyphs.c
index 5c84f13..603c4e5 100644
--- a/src/display/nr-arena-glyphs.c
+++ b/src/display/nr-arena-glyphs.c
@@ -452,7 +452,7 @@ nr_arena_glyphs_group_render (NRArenaItem *item, NRRectL *area, NRPixBlock *pb,
if (style->fill.type != SP_PAINT_TYPE_NONE) {
NRPixBlock mb;
guint32 rgba;
- nr_pixblock_setup_fast (&mb, NR_PIXBLOCK_MODE_A8, area->x0, area->y0, area->x1, area->y1, TRUE);
+ nr_pixblock_setup_fast (&mb, NR_PIXBLOCK_MODE_G8, area->x0, area->y0, area->x1, area->y1, TRUE);
/* Render children fill mask */
for (child = group->children; child != NULL; child = child->next) {
ret = nr_arena_glyphs_fill_mask (NR_ARENA_GLYPHS (child), area, &mb);
@@ -493,7 +493,7 @@ nr_arena_glyphs_group_render (NRArenaItem *item, NRRectL *area, NRPixBlock *pb,
if (style->stroke.type != SP_PAINT_TYPE_NONE) {
NRPixBlock m;
guint32 rgba;
- nr_pixblock_setup_fast (&m, NR_PIXBLOCK_MODE_A8, area->x0, area->y0, area->x1, area->y1, TRUE);
+ nr_pixblock_setup_fast (&m, NR_PIXBLOCK_MODE_G8, area->x0, area->y0, area->x1, area->y1, TRUE);
/* Render children stroke mask */
for (child = group->children; child != NULL; child = child->next) {
ret = nr_arena_glyphs_stroke_mask (NR_ARENA_GLYPHS (child), area, &m);
diff --git a/src/display/nr-arena-item.c b/src/display/nr-arena-item.c
index 0a154fe..6e36d84 100644
--- a/src/display/nr-arena-item.c
+++ b/src/display/nr-arena-item.c
@@ -329,7 +329,7 @@ nr_arena_item_invoke_render (NRArenaItem *item, NRRectL *area, NRPixBlock *pb, u
if (item->clip || item->mask) {
/* Setup mask pixblock */
- nr_pixblock_setup_fast (&mpb, NR_PIXBLOCK_MODE_A8, carea.x0, carea.y0, carea.x1, carea.y1, TRUE);
+ nr_pixblock_setup_fast (&mpb, NR_PIXBLOCK_MODE_G8, carea.x0, carea.y0, carea.x1, carea.y1, TRUE);
/* Do clip if needed */
if (item->clip) {
state = nr_arena_item_invoke_clip (item->clip, &carea, &mpb);
diff --git a/src/display/nr-arena-shape.c b/src/display/nr-arena-shape.c
index 69b6a68..54fa79d 100644
--- a/src/display/nr-arena-shape.c
+++ b/src/display/nr-arena-shape.c
@@ -452,7 +452,7 @@ nr_arena_shape_render (NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigne
NRPixBlock m;
guint32 rgba;
- nr_pixblock_setup_fast (&m, NR_PIXBLOCK_MODE_A8, area->x0, area->y0, area->x1, area->y1, TRUE);
+ nr_pixblock_setup_fast (&m, NR_PIXBLOCK_MODE_G8, area->x0, area->y0, area->x1, area->y1, TRUE);
nr_pixblock_render_svp_mask_or (&m, shape->fill_svp);
m.empty = FALSE;
@@ -489,7 +489,7 @@ nr_arena_shape_render (NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigne
NRPixBlock m;
guint32 rgba;
- nr_pixblock_setup_fast (&m, NR_PIXBLOCK_MODE_A8, area->x0, area->y0, area->x1, area->y1, TRUE);
+ nr_pixblock_setup_fast (&m, NR_PIXBLOCK_MODE_G8, area->x0, area->y0, area->x1, area->y1, TRUE);
nr_pixblock_render_svp_mask_or (&m, shape->stroke_svp);
m.empty = FALSE;
diff --git a/src/helper/nr-gradient-gpl.c b/src/helper/nr-gradient-gpl.c
index c480996..e03bee0 100644
--- a/src/helper/nr-gradient-gpl.c
+++ b/src/helper/nr-gradient-gpl.c
@@ -84,7 +84,7 @@ nr_lgradient_render_block (NRRenderer *r, NRPixBlock *pb, NRPixBlock *m)
#else
if (pb->empty) {
switch (pb->mode) {
- case NR_PIXBLOCK_MODE_A8:
+ case NR_PIXBLOCK_MODE_G8:
nr_lgradient_render_generic (lgr, pb);
break;
case NR_PIXBLOCK_MODE_R8G8B8:
@@ -101,7 +101,7 @@ nr_lgradient_render_block (NRRenderer *r, NRPixBlock *pb, NRPixBlock *m)
}
} else {
switch (pb->mode) {
- case NR_PIXBLOCK_MODE_A8:
+ case NR_PIXBLOCK_MODE_G8:
nr_lgradient_render_generic (lgr, pb);
break;
case NR_PIXBLOCK_MODE_R8G8B8:
@@ -283,7 +283,7 @@ nr_lgradient_render_generic (NRLGradientRenderer *lgr, NRPixBlock *pb)
(unsigned char *) lgr->vector,
4 * NR_GRADIENT_VECTOR_LENGTH,
0, 0);
- bpp = (pb->mode == NR_PIXBLOCK_MODE_A8) ? 1 : (pb->mode == NR_PIXBLOCK_MODE_R8G8B8) ? 3 : 4;
+ bpp = (pb->mode == NR_PIXBLOCK_MODE_G8) ? 1 : (pb->mode == NR_PIXBLOCK_MODE_R8G8B8) ? 3 : 4;
for (y = 0; y < height; y++) {
d = NR_PIXBLOCK_PX (pb) + y * rs;
diff --git a/src/libnr/nr-blit.c b/src/libnr/nr-blit.c
index ac605ac..60d027c 100644
--- a/src/libnr/nr-blit.c
+++ b/src/libnr/nr-blit.c
@@ -12,22 +12,21 @@
#include "nr-rect.h"
#include "nr-pixops.h"
#include "nr-compose.h"
+#include "nr-pixblock.h"
+
#include "nr-blit.h"
void
-nr_blit_pixblock_pixblock_alpha (NRPixBlock *d, NRPixBlock *s, unsigned int alpha)
+nr_blit_pixblock_pixblock_alpha (NRPixBlock *d, const NRPixBlock *s, unsigned int alpha)
{
NRRectS clip;
- unsigned char *dpx, *spx;
+ unsigned char *dpx;
+ const unsigned char *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:
@@ -64,14 +63,34 @@ nr_blit_pixblock_pixblock_alpha (NRPixBlock *d, NRPixBlock *s, unsigned int alph
h = clip.y1 - clip.y0;
switch (d->mode) {
- case NR_PIXBLOCK_MODE_A8:
- /* No rendering into alpha at moment */
+ case NR_PIXBLOCK_MODE_G8:
+ if (d->empty) {
+ if (s->mode == NR_PIXBLOCK_MODE_G8) {
+ nr_A8_EMPTY_A8 (dpx, w, h, d->rs, spx, s->rs, alpha);
+ } else if (s->mode == NR_PIXBLOCK_MODE_R8G8B8) {
+ nr_A8_EMPTY_R8G8B8 (dpx, w, h, d->rs, spx, s->rs, alpha);
+ } else if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8N) {
+ nr_A8_EMPTY_R8G8B8A8_N (dpx, w, h, d->rs, spx, s->rs, alpha);
+ } else if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) {
+ nr_A8_EMPTY_R8G8B8A8_P (dpx, w, h, d->rs, spx, s->rs, alpha);
+ }
+ } else {
+ /* fixme: Implement (Lauris) */
+ }
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);
+ if (d->empty) {
+ /* fixme: Implement (Lauris) */
} else {
- nr_R8G8B8_R8G8B8_R8G8B8A8_N (dpx, w, h, d->rs, spx, s->rs, alpha);
+ if (s->mode == NR_PIXBLOCK_MODE_G8) {
+ /* fixme: Implement mask rendering (Lauris) */
+ } else if (s->mode == NR_PIXBLOCK_MODE_R8G8B8) {
+ nr_R8G8B8_R8G8B8_R8G8B8 (dpx, w, h, d->rs, spx, s->rs, alpha);
+ } else if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8N) {
+ nr_R8G8B8_R8G8B8_R8G8B8A8_N (dpx, w, h, d->rs, spx, s->rs, alpha);
+ } else {
+ nr_R8G8B8_R8G8B8_R8G8B8A8_P (dpx, w, h, d->rs, spx, s->rs, alpha);
+ }
}
break;
case NR_PIXBLOCK_MODE_R8G8B8A8P:
@@ -79,36 +98,46 @@ nr_blit_pixblock_pixblock_alpha (NRPixBlock *d, NRPixBlock *s, unsigned int alph
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 {
+ } else if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8N) {
/* Case C */
nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N (dpx, w, h, d->rs, spx, s->rs, alpha);
+ } else {
+ /* fixme: Implement mask and RGB rendering (Lauris) */
}
} 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 {
+ } else if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8N) {
/* case E */
nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N (dpx, w, h, d->rs, spx, s->rs, alpha);
+ } else {
+ /* fixme: Implement mask and RGB rendering (Lauris) */
}
}
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 */
+ if (s->mode == NR_PIXBLOCK_MODE_G8) {
+ /* fixme: Implement (Lauris) */
+ } else if (s->mode == NR_PIXBLOCK_MODE_R8G8B8) {
+ nr_R8G8B8A8_N_EMPTY_R8G8B8 (dpx, w, h, d->rs, spx, s->rs, alpha);
+ } else if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8N) {
nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N (dpx, w, h, d->rs, spx, s->rs, alpha);
+ } else {
+ nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P (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 {
+ } else if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8N) {
/* case F */
nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N (dpx, w, h, d->rs, spx, s->rs, alpha);
+ } else if (s->mode == NR_PIXBLOCK_MODE_R8G8B8) {
+ nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8 (dpx, w, h, d->rs, spx, s->rs, alpha);
+ } else {
+ /* fixme: Implement mask rendering (Lauris) */
}
}
break;
@@ -116,18 +145,15 @@ nr_blit_pixblock_pixblock_alpha (NRPixBlock *d, NRPixBlock *s, unsigned int alph
}
void
-nr_blit_pixblock_pixblock_mask (NRPixBlock *d, NRPixBlock *s, NRPixBlock *m)
+nr_blit_pixblock_pixblock_mask (NRPixBlock *d, const NRPixBlock *s, const NRPixBlock *m)
{
NRRectS clip;
- unsigned char *dpx, *spx, *mpx;
+ unsigned char *dpx;
+ const unsigned char *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:
@@ -166,7 +192,7 @@ nr_blit_pixblock_pixblock_mask (NRPixBlock *d, NRPixBlock *s, NRPixBlock *m)
h = clip.y1 - clip.y0;
switch (d->mode) {
- case NR_PIXBLOCK_MODE_A8:
+ case NR_PIXBLOCK_MODE_G8:
/* No rendering into alpha at moment */
break;
case NR_PIXBLOCK_MODE_R8G8B8:
@@ -197,12 +223,14 @@ nr_blit_pixblock_pixblock_mask (NRPixBlock *d, NRPixBlock *s, NRPixBlock *m)
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 */
+ if (s->mode == NR_PIXBLOCK_MODE_G8) {
+ nr_R8G8B8A8_N_EMPTY_A8_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs);
+ } else if (s->mode == NR_PIXBLOCK_MODE_R8G8B8) {
+ nr_R8G8B8A8_N_EMPTY_R8G8B8_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs);
+ } else if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8N) {
nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs);
+ } else {
+ nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs);
}
} else {
if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) {
@@ -218,16 +246,17 @@ nr_blit_pixblock_pixblock_mask (NRPixBlock *d, NRPixBlock *s, NRPixBlock *m)
}
void
-nr_blit_pixblock_mask_rgba32 (NRPixBlock *d, NRPixBlock *m, unsigned long rgba)
+nr_blit_pixblock_mask_rgba32 (NRPixBlock *d, const NRPixBlock *m, unsigned long rgba)
{
if (!(rgba & 0xff)) return;
if (m) {
NRRectS clip;
- unsigned char *dpx, *mpx;
+ unsigned char *dpx;
+ const unsigned char *mpx;
int w, h;
- if (m->mode != NR_PIXBLOCK_MODE_A8) return;
+ if (m->mode != NR_PIXBLOCK_MODE_G8) return;
if (!nr_rect_s_test_intersect (&d->area, &m->area)) return;
diff --git a/src/libnr/nr-blit.h b/src/libnr/nr-blit.h
index 9bc5780..d2f2b72 100644
--- a/src/libnr/nr-blit.h
+++ b/src/libnr/nr-blit.h
@@ -18,9 +18,9 @@ extern "C" {
#define nr_blit_pixblock_pixblock(d,s) nr_blit_pixblock_pixblock_alpha (d, s, 255)
-void nr_blit_pixblock_pixblock_alpha (NRPixBlock *d, NRPixBlock *s, unsigned int alpha);
-void nr_blit_pixblock_pixblock_mask (NRPixBlock *d, NRPixBlock *s, NRPixBlock *m);
-void nr_blit_pixblock_mask_rgba32 (NRPixBlock *d, NRPixBlock *m, unsigned long rgba32);
+void nr_blit_pixblock_pixblock_alpha (NRPixBlock *d, const NRPixBlock *s, unsigned int alpha);
+void nr_blit_pixblock_pixblock_mask (NRPixBlock *d, const NRPixBlock *s, const NRPixBlock *m);
+void nr_blit_pixblock_mask_rgba32 (NRPixBlock *d, const NRPixBlock *m, unsigned long rgba32);
#ifdef __cplusplus
};
diff --git a/src/libnr/nr-compose.c b/src/libnr/nr-compose.c
index 0d6ed4c..428bba6 100644
--- a/src/libnr/nr-compose.c
+++ b/src/libnr/nr-compose.c
@@ -27,6 +27,175 @@ void nr_mmx_R8G8B8_R8G8B8_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, c
#endif
void
+nr_A8_EMPTY_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
+{
+ int r, c;
+ if (alpha == 0) {
+ /* Clear destination */
+ for (r = 0; r < h; r++) {
+ memset (px, 0x0, w);
+ px += rs;
+ }
+ } else if (alpha == 255) {
+ /* Copy source */
+ for (r = 0; r < h; r++) {
+ memcpy (px, spx, w);
+ px += rs;
+ spx += srs;
+ }
+ } else {
+ /* Copy multiplied */
+ const unsigned char *s;
+ unsigned char *d;
+ d = px;
+ s = spx;
+ for (c = 0; c < w; c++) {
+ d[0] = (s[0] * alpha + 127) / 255;
+ d += 1;
+ s += 1;
+ }
+ px += rs;
+ spx += srs;
+ }
+}
+
+void
+nr_A8_EMPTY_R8G8B8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
+{
+ int r, c;
+ if (alpha == 0) {
+ /* Clear destination */
+ for (r = 0; r < h; r++) {
+ memset (px, 0x0, w);
+ px += rs;
+ }
+ } else if (alpha == 255) {
+ /* Copy average */
+ for (r = 0; r < h; r++) {
+ const unsigned char *s;
+ unsigned char *d;
+ d = px;
+ s = spx;
+ for (c = 0; c < w; c++) {
+ d[0] = (s[0] + s[1] + s[2] + 1) / 3;
+ d += 1;
+ s += 3;
+ }
+ px += rs;
+ spx += srs;
+ }
+ } else {
+ /* Copy average multiplied */
+ for (r = 0; r < h; r++) {
+ const unsigned char *s;
+ unsigned char *d;
+ d = px;
+ s = spx;
+ for (c = 0; c < w; c++) {
+ d[0] = ((s[0] + s[1] + s[2]) * alpha + 383) / 767;
+ d += 1;
+ s += 3;
+ }
+ px += rs;
+ spx += srs;
+ }
+ }
+}
+
+/* fixme: This composition is not 100% correct */
+
+void
+nr_A8_EMPTY_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
+{
+ int r, c;
+ if (alpha == 0) {
+ /* Clear destination */
+ for (r = 0; r < h; r++) {
+ memset (px, 0x0, w);
+ px += rs;
+ }
+ } else {
+ /* Copy average multiplied */
+ for (r = 0; r < h; r++) {
+ const unsigned char *s;
+ unsigned char *d;
+ d = px;
+ s = spx;
+ for (c = 0; c < w; c++) {
+ d[0] = ((s[0] + s[1] + s[2]) * alpha + 383) / 767;
+ d += 1;
+ s += 4;
+ }
+ px += rs;
+ spx += srs;
+ }
+ }
+}
+
+/* fixme: This composition is not 100% correct */
+
+void
+nr_A8_EMPTY_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
+{
+ int r, c;
+ if (alpha == 0) {
+ /* Clear destination */
+ for (r = 0; r < h; r++) {
+ memset (px, 0x0, w);
+ px += rs;
+ }
+ } else {
+ /* Copy average multiplied */
+ for (r = 0; r < h; r++) {
+ const unsigned char *s;
+ unsigned char *d;
+ d = px;
+ s = spx;
+ for (c = 0; c < w; c++) {
+ unsigned int a;
+ a = NR_PREMUL (s[3], alpha);
+ if (a == 0) {
+ d[0] = ((s[0] + s[1] + s[2]) * alpha + 383) / 767;
+ } else if (a == 255) {
+ d[0] = (s[0] + s[1] + s[2] + 1) / 3;
+ } else {
+ d[0] = ((s[0] + s[1] + s[2]) * 255 + a) / (3 * a);
+ }
+ d += 1;
+ s += 4;
+ }
+ px += rs;
+ spx += srs;
+ }
+ }
+}
+
+void
+nr_R8G8B8A8_N_EMPTY_R8G8B8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
+{
+ int r, c;
+
+ for (r = 0; r < h; r++) {
+ if (alpha == 0) {
+ memset (px, 0x0, 4 * w);
+ } else {
+ const unsigned char *s;
+ unsigned char *d;
+ d = px;
+ s = spx;
+ for (c = 0; c < w; c++) {
+ *d++ = *s++;
+ *d++ = *s++;
+ *d++ = *s++;
+ *d++ = alpha;
+ }
+ }
+ px += rs;
+ spx += srs;
+ }
+}
+
+void
nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
{
int r, c;
@@ -52,7 +221,6 @@ nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const u
spx += srs;
}
}
-
void
nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
{
@@ -147,6 +315,44 @@ nr_R8G8B8A8_P_EMPTY_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const u
}
}
+/* fixme: This is not optimized (Lauris) */
+void
+nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
+{
+ int r, c;
+
+ if (alpha == 0) return;
+
+ for (r = 0; r < h; r++) {
+ unsigned char *d, *s;
+ d = (unsigned char *) px;
+ s = (unsigned char *) spx;
+ for (c = 0; c < w; c++) {
+ unsigned int a;
+ a = alpha;
+ if ((a == 255) || (d[3] == 0)) {
+ /* Full coverage, COPY */
+ d[0] = s[0];
+ d[1] = s[1];
+ d[2] = s[2];
+ d[3] = a;
+ } else {
+ unsigned int ca;
+ /* Full composition */
+ ca = 65025 - (255 - a) * (255 - d[3]);
+ d[0] = NR_COMPOSENNN_A7 (s[0], a, d[0], d[3], ca);
+ d[1] = NR_COMPOSENNN_A7 (s[1], a, d[1], d[3], ca);
+ d[2] = NR_COMPOSENNN_A7 (s[2], a, d[2], d[3], ca);
+ d[3] = (ca + 127) / 255;
+ }
+ d += 4;
+ s += 3;
+ }
+ px += rs;
+ spx += srs;
+ }
+}
+
void
nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
{
@@ -317,10 +523,57 @@ nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, co
/* Masked operations */
void
-nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs)
+nr_R8G8B8A8_N_EMPTY_A8_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs)
{
int x, y;
+ for (y = 0; y < h; y++) {
+ unsigned char *d, *s, *m;
+ d = (unsigned char *) px;
+ s = (unsigned char *) spx;
+ m = (unsigned char *) mpx;
+ for (x = 0; x < w; x++) {
+ d[0] = s[0];
+ d[1] = s[0];
+ d[2] = s[0];
+ d[3] = m[0];
+ d += 4;
+ s += 1;
+ m += 1;
+ }
+ px += rs;
+ spx += srs;
+ mpx += mrs;
+ }
+}
+
+void
+nr_R8G8B8A8_N_EMPTY_R8G8B8_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs)
+{
+ int x, y;
+ for (y = 0; y < h; y++) {
+ unsigned char *d, *s, *m;
+ d = (unsigned char *) px;
+ s = (unsigned char *) spx;
+ m = (unsigned char *) mpx;
+ for (x = 0; x < w; x++) {
+ d[0] = s[0];
+ d[1] = s[1];
+ d[2] = s[2];
+ d[3] = m[0];
+ d += 4;
+ s += 3;
+ m += 1;
+ }
+ px += rs;
+ spx += srs;
+ mpx += mrs;
+ }
+}
+void
+nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs)
+{
+ int x, y;
for (y = 0; y < h; y++) {
unsigned char *d, *s, *m;
d = (unsigned char *) px;
@@ -855,6 +1108,36 @@ nr_R8G8B8A8_P_R8G8B8A8_P_A8_RGBA32 (unsigned char *px, int w, int h, int rs, con
/* RGB */
void
+nr_R8G8B8_R8G8B8_R8G8B8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
+{
+ int r, c;
+
+ if (alpha == 0) return;
+
+ for (r = 0; r < h; r++) {
+ const unsigned char *s;
+ unsigned char *d;
+ d = px;
+ s = spx;
+ for (c = 0; c < w; c++) {
+ if (alpha == 255) {
+ d[0] = s[0];
+ d[1] = s[1];
+ d[2] = s[2];
+ } else {
+ d[0] = NR_COMPOSEN11 (s[0], alpha, d[0]);
+ d[1] = NR_COMPOSEN11 (s[1], alpha, d[1]);
+ d[2] = NR_COMPOSEN11 (s[2], alpha, d[2]);
+ }
+ d += 3;
+ s += 3;
+ }
+ px += rs;
+ spx += srs;
+ }
+}
+
+void
nr_R8G8B8_R8G8B8_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
{
int r, c;
diff --git a/src/libnr/nr-compose.h b/src/libnr/nr-compose.h
index 3fb1e5f..c3eafb9 100644
--- a/src/libnr/nr-compose.h
+++ b/src/libnr/nr-compose.h
@@ -12,24 +12,36 @@
/* FINAL DST SRC */
+/* Destination A8 EMPTY */
+void nr_A8_EMPTY_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
+void nr_A8_EMPTY_R8G8B8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
+void nr_A8_EMPTY_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
+void nr_A8_EMPTY_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
+
+/* Destination R8G8B8 */
+void nr_R8G8B8_R8G8B8_R8G8B8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
+void nr_R8G8B8_R8G8B8_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
+void nr_R8G8B8_R8G8B8_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
+
+void nr_R8G8B8A8_N_EMPTY_R8G8B8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
void nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
void nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
void nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
void nr_R8G8B8A8_P_EMPTY_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
+void nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
void nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
void nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
void nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
void nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
/* FINAL DST SRC MASK */
+/* Destination R8G8B8A8 EMPTY */
+void nr_R8G8B8A8_N_EMPTY_A8_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs);
+void nr_R8G8B8A8_N_EMPTY_R8G8B8_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs);
+void nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs);
+void nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs);
-void nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N_A8 (unsigned char *px, int w, int h, int rs,
- const unsigned char *spx, int srs,
- const unsigned char *mpx, int mrs);
-void nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P_A8 (unsigned char *px, int w, int h, int rs,
- const unsigned char *spx, int srs,
- const unsigned char *mpx, int mrs);
void nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N_A8 (unsigned char *px, int w, int h, int rs,
const unsigned char *spx, int srs,
const unsigned char *mpx, int mrs);
@@ -62,10 +74,6 @@ void nr_R8G8B8_R8G8B8_A8_RGBA32 (unsigned char *px, int w, int h, int rs, const
void nr_R8G8B8A8_N_R8G8B8A8_N_A8_RGBA32 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned long rgba);
void nr_R8G8B8A8_P_R8G8B8A8_P_A8_RGBA32 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned long rgba);
-/* RGB */
-
-void nr_R8G8B8_R8G8B8_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
-void nr_R8G8B8_R8G8B8_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
void nr_R8G8B8_R8G8B8_R8G8B8A8_P_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs);
void nr_R8G8B8_R8G8B8_R8G8B8A8_N_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs);
diff --git a/src/libnr/nr-gradient.c b/src/libnr/nr-gradient.c
index 517948b..30e7531 100644
--- a/src/libnr/nr-gradient.c
+++ b/src/libnr/nr-gradient.c
@@ -246,7 +246,7 @@ nr_rgradient_render_generic_symmetric (NRRGradientRenderer *rgr, NRPixBlock *pb)
(unsigned char *) rgr->vector,
4 * NR_GRADIENT_VECTOR_LENGTH,
0, 0);
- bpp = (pb->mode == NR_PIXBLOCK_MODE_A8) ? 1 : (pb->mode == NR_PIXBLOCK_MODE_R8G8B8) ? 3 : 4;
+ bpp = (pb->mode == NR_PIXBLOCK_MODE_G8) ? 1 : (pb->mode == NR_PIXBLOCK_MODE_R8G8B8) ? 3 : 4;
for (y = pb->area.y0; y < pb->area.y1; y++) {
double gx, gy;
@@ -298,7 +298,7 @@ nr_rgradient_render_generic_optimized (NRRGradientRenderer *rgr, NRPixBlock *pb)
(unsigned char *) rgr->vector,
4 * NR_GRADIENT_VECTOR_LENGTH,
0, 0);
- bpp = (pb->mode == NR_PIXBLOCK_MODE_A8) ? 1 : (pb->mode == NR_PIXBLOCK_MODE_R8G8B8) ? 3 : 4;
+ bpp = (pb->mode == NR_PIXBLOCK_MODE_G8) ? 1 : (pb->mode == NR_PIXBLOCK_MODE_R8G8B8) ? 3 : 4;
r = MAX (rgr->r, 1e-9);
diff --git a/src/libnr/nr-pixblock-pattern.c b/src/libnr/nr-pixblock-pattern.c
index 7a0a173..56edbd8 100644
--- a/src/libnr/nr-pixblock-pattern.c
+++ b/src/libnr/nr-pixblock-pattern.c
@@ -50,7 +50,7 @@ nr_pixblock_render_gray_noise (NRPixBlock *pb, NRPixBlock *mask)
for (x = clip.x0; x < clip.x1; x++) {
v = v ^ noise[seed];
switch (pb->mode) {
- case NR_PIXBLOCK_MODE_A8:
+ case NR_PIXBLOCK_MODE_G8:
d[0] = (65025 - (255 - m[0]) * (255 - d[0]) + 127) / 255;
break;
case NR_PIXBLOCK_MODE_R8G8B8:
@@ -94,7 +94,7 @@ nr_pixblock_render_gray_noise (NRPixBlock *pb, NRPixBlock *mask)
for (x = clip.x0; x < clip.x1; x++) {
v = v ^ noise[seed];
switch (pb->mode) {
- case NR_PIXBLOCK_MODE_A8:
+ case NR_PIXBLOCK_MODE_G8:
d[0] = 255;
break;
case NR_PIXBLOCK_MODE_R8G8B8:
diff --git a/src/libnr/nr-pixblock-pixel.c b/src/libnr/nr-pixblock-pixel.c
index 2befa95..c500fe6 100644
--- a/src/libnr/nr-pixblock-pixel.c
+++ b/src/libnr/nr-pixblock-pixel.c
@@ -20,9 +20,9 @@ nr_compose_pixblock_pixblock_pixel (NRPixBlock *dpb, unsigned char *d, const NRP
if (dpb->empty) {
/* Empty destination */
switch (dpb->mode) {
- case NR_PIXBLOCK_MODE_A8:
+ case NR_PIXBLOCK_MODE_G8:
switch (spb->mode) {
- case NR_PIXBLOCK_MODE_A8:
+ case NR_PIXBLOCK_MODE_G8:
break;
case NR_PIXBLOCK_MODE_R8G8B8:
d[0] = 255;
@@ -39,7 +39,7 @@ nr_compose_pixblock_pixblock_pixel (NRPixBlock *dpb, unsigned char *d, const NRP
break;
case NR_PIXBLOCK_MODE_R8G8B8:
switch (spb->mode) {
- case NR_PIXBLOCK_MODE_A8:
+ case NR_PIXBLOCK_MODE_G8:
break;
case NR_PIXBLOCK_MODE_R8G8B8:
d[0] = s[0];
@@ -62,7 +62,7 @@ nr_compose_pixblock_pixblock_pixel (NRPixBlock *dpb, unsigned char *d, const NRP
break;
case NR_PIXBLOCK_MODE_R8G8B8A8N:
switch (spb->mode) {
- case NR_PIXBLOCK_MODE_A8:
+ case NR_PIXBLOCK_MODE_G8:
break;
case NR_PIXBLOCK_MODE_R8G8B8:
d[0] = s[0];
@@ -94,7 +94,7 @@ nr_compose_pixblock_pixblock_pixel (NRPixBlock *dpb, unsigned char *d, const NRP
break;
case NR_PIXBLOCK_MODE_R8G8B8A8P:
switch (spb->mode) {
- case NR_PIXBLOCK_MODE_A8:
+ case NR_PIXBLOCK_MODE_G8:
break;
case NR_PIXBLOCK_MODE_R8G8B8:
d[0] = s[0];
@@ -124,9 +124,9 @@ nr_compose_pixblock_pixblock_pixel (NRPixBlock *dpb, unsigned char *d, const NRP
} else {
/* Image destination */
switch (dpb->mode) {
- case NR_PIXBLOCK_MODE_A8:
+ case NR_PIXBLOCK_MODE_G8:
switch (spb->mode) {
- case NR_PIXBLOCK_MODE_A8:
+ case NR_PIXBLOCK_MODE_G8:
break;
case NR_PIXBLOCK_MODE_R8G8B8:
d[0] = 255;
@@ -143,7 +143,7 @@ nr_compose_pixblock_pixblock_pixel (NRPixBlock *dpb, unsigned char *d, const NRP
break;
case NR_PIXBLOCK_MODE_R8G8B8:
switch (spb->mode) {
- case NR_PIXBLOCK_MODE_A8:
+ case NR_PIXBLOCK_MODE_G8:
break;
case NR_PIXBLOCK_MODE_R8G8B8:
d[0] = s[0];
@@ -166,7 +166,7 @@ nr_compose_pixblock_pixblock_pixel (NRPixBlock *dpb, unsigned char *d, const NRP
break;
case NR_PIXBLOCK_MODE_R8G8B8A8N:
switch (spb->mode) {
- case NR_PIXBLOCK_MODE_A8:
+ case NR_PIXBLOCK_MODE_G8:
break;
case NR_PIXBLOCK_MODE_R8G8B8:
d[0] = s[0];
@@ -199,7 +199,7 @@ nr_compose_pixblock_pixblock_pixel (NRPixBlock *dpb, unsigned char *d, const NRP
break;
case NR_PIXBLOCK_MODE_R8G8B8A8P:
switch (spb->mode) {
- case NR_PIXBLOCK_MODE_A8:
+ case NR_PIXBLOCK_MODE_G8:
break;
case NR_PIXBLOCK_MODE_R8G8B8:
d[0] = s[0];
diff --git a/src/libnr/nr-pixblock.c b/src/libnr/nr-pixblock.c
index 8a52ecd..a26a561 100644
--- a/src/libnr/nr-pixblock.c
+++ b/src/libnr/nr-pixblock.c
@@ -14,8 +14,6 @@
#include "nr-macros.h"
#include "nr-pixblock.h"
-#define NR_TINY_MAX sizeof (unsigned char *)
-
void
nr_pixblock_setup_fast (NRPixBlock *pb, int mode, int x0, int y0, int x1, int y1, int clear)
{
@@ -23,13 +21,20 @@ nr_pixblock_setup_fast (NRPixBlock *pb, int mode, int x0, int y0, int x1, int y1
w = x1 - x0;
h = y1 - y0;
- bpp = (mode == NR_PIXBLOCK_MODE_A8) ? 1 : (mode == NR_PIXBLOCK_MODE_R8G8B8) ? 3 : 4;
+ bpp = NR_PIXBLOCK_MODE_BPP (mode);
- size = bpp * w * h;
+ pb->mode = mode;
+ pb->area.x0 = x0;
+ pb->area.y0 = y0;
+ pb->area.x1 = x1;
+ pb->area.y1 = y1;
+ pb->rs = (bpp * w + 3) & 0xfffffffc;
+
+ size = h * pb->rs;
if (size <= NR_TINY_MAX) {
pb->size = NR_PIXBLOCK_SIZE_TINY;
- if (clear) memset (pb->data.p, 0x0, size);
+ if (clear && size) memset (pb->data.p, 0x0, size);
} else if (size <= 4096) {
pb->size = NR_PIXBLOCK_SIZE_4K;
pb->data.px = nr_pixelstore_4K_new (clear, 0x0);
@@ -45,13 +50,7 @@ nr_pixblock_setup_fast (NRPixBlock *pb, int mode, int x0, int y0, int x1, int y1
if (clear) memset (pb->data.px, 0x0, size);
}
- pb->mode = mode;
pb->empty = 1;
- pb->area.x0 = x0;
- pb->area.y0 = y0;
- pb->area.x1 = x1;
- pb->area.y1 = y1;
- pb->rs = bpp * w;
}
void
@@ -61,26 +60,27 @@ nr_pixblock_setup (NRPixBlock *pb, int mode, int x0, int y0, int x1, int y1, int
w = x1 - x0;
h = y1 - y0;
- bpp = (mode == NR_PIXBLOCK_MODE_A8) ? 1 : (mode == NR_PIXBLOCK_MODE_R8G8B8) ? 3 : 4;
+ bpp = NR_PIXBLOCK_MODE_BPP (mode);
+
+ pb->mode = mode;
+ pb->area.x0 = x0;
+ pb->area.y0 = y0;
+ pb->area.x1 = x1;
+ pb->area.y1 = y1;
+ pb->rs = (bpp * w + 3) & 0xfffffffc;
- size = bpp * w * h;
+ size = h * pb->rs;
if (size <= NR_TINY_MAX) {
pb->size = NR_PIXBLOCK_SIZE_TINY;
- if (clear) memset (pb->data.p, 0x0, size);
+ if (clear && size) memset (pb->data.p, 0x0, size);
} else {
pb->size = NR_PIXBLOCK_SIZE_BIG;
pb->data.px = nr_new (unsigned char, size);
if (clear) memset (pb->data.px, 0x0, size);
}
- pb->mode = mode;
pb->empty = 1;
- pb->area.x0 = x0;
- pb->area.y0 = y0;
- pb->area.x1 = x1;
- pb->area.y1 = y1;
- pb->rs = bpp * w;
}
void
@@ -89,7 +89,7 @@ nr_pixblock_setup_extern (NRPixBlock *pb, int mode, int x0, int y0, int x1, int
int w, bpp;
w = x1 - x0;
- bpp = (mode == NR_PIXBLOCK_MODE_A8) ? 1 : (mode == NR_PIXBLOCK_MODE_R8G8B8) ? 3 : 4;
+ bpp = (mode == NR_PIXBLOCK_MODE_G8) ? 1 : (mode == NR_PIXBLOCK_MODE_R8G8B8) ? 3 : 4;
pb->size = NR_PIXBLOCK_SIZE_STATIC;
pb->mode = mode;
@@ -160,6 +160,172 @@ nr_pixblock_free (NRPixBlock *pb)
return NULL;
}
+/* Helpers */
+
+unsigned int
+nr_pixblock_has_alpha (const NRPixBlock *pb)
+{
+ if (!pb) return 0;
+ if (pb->mode == NR_PIXBLOCK_MODE_R8G8B8A8N) return 1;
+ if (pb->mode == NR_PIXBLOCK_MODE_R8G8B8A8N) return 1;
+ return 0;
+}
+
+void
+nr_pixblock_get_channel_limits (const NRPixBlock *pb, unsigned int minv[], unsigned int maxv[])
+{
+ int x, y, bpp, c;
+ bpp = NR_PIXBLOCK_BPP(pb);
+ for (c = 0; c < bpp; c++) {
+ minv[c] = 255;
+ maxv[c] = 0;
+ }
+ for (y = pb->area.y0; y < pb->area.y1; y++) {
+ const unsigned char *s;
+ s = NR_PIXBLOCK_PX (pb) + (y - pb->area.y0) * pb->rs;
+ for (x = pb->area.x0; x < pb->area.x1; x++) {
+ for (c = 0; c < bpp; c++) {
+ if (s[c] < minv[c]) minv[c] = s[c];
+ if (s[c] > maxv[c]) maxv[c] = s[c];
+ }
+ s += bpp;
+ }
+ }
+}
+
+void
+nr_pixblock_get_histogram (const NRPixBlock *pb, unsigned int histogram[][256])
+{
+ int x, y, bpp, c, v;
+ bpp = NR_PIXBLOCK_BPP(pb);
+ for (c = 0; c < bpp; c++) {
+ for (v = 0; v < 256; v++) histogram[c][v] = 0;
+ }
+ for (y = pb->area.y0; y < pb->area.y1; y++) {
+ const unsigned char *s;
+ s = NR_PIXBLOCK_PX (pb) + (y - pb->area.y0) * pb->rs;
+ for (x = pb->area.x0; x < pb->area.x1; x++) {
+ for (c = 0; c < bpp; c++) {
+ histogram[c][s[c]] += 1;
+ }
+ s += bpp;
+ }
+ }
+}
+
+unsigned int
+nr_pixblock_get_crc32 (const NRPixBlock *pb)
+{
+ unsigned int crc32, acc;
+ unsigned int width, height, bpp, x, y, c, cnt;
+ width = pb->area.x1 - pb->area.x0;
+ height = pb->area.y1 - pb->area.y0;
+ bpp = NR_PIXBLOCK_BPP(pb);
+ crc32 = 0;
+ acc = 0;
+ cnt = 0;
+ for (y = 0; y < height; y++) {
+ const unsigned char *s = NR_PIXBLOCK_ROW(pb, y);
+ for (x = 0; x < width; x++) {
+ for (c = 0; c < bpp; c++) {
+ acc <<= 8;
+ acc |= *s++;
+ if (++cnt >= 4) {
+ crc32 ^= acc;
+ acc = cnt = 0;
+ }
+ }
+ }
+ crc32 ^= acc;
+ acc = cnt = 0;
+ }
+ return crc32;
+}
+
+NRULongLong
+nr_pixblock_get_crc64 (const NRPixBlock *pb)
+{
+ NRULongLong crc64, acc, carry;
+ unsigned int width, height, bpp, x, y, c, cnt;
+ width = pb->area.x1 - pb->area.x0;
+ height = pb->area.y1 - pb->area.y0;
+ bpp = NR_PIXBLOCK_BPP(pb);
+ crc64 = 0;
+ acc = 0;
+ carry = 0;
+ cnt = 0;
+ for (y = 0; y < height; y++) {
+ const unsigned char *s = NR_PIXBLOCK_ROW(pb, y);
+ for (x = 0; x < width; x++) {
+ for (c = 0; c < bpp; c++) {
+ acc <<= 8;
+ acc |= *s++;
+ if (++cnt >= 8) {
+ if ((crc64 & 0x8000000000000000) && (acc & 0x8000000000000000)) carry = 1;
+ crc64 += acc;
+ crc64 += carry;
+ acc = carry = 0;
+ cnt = 0;
+ }
+ }
+ }
+ crc64 += acc;
+ acc = cnt = 0;
+ }
+ return crc64;
+}
+
+unsigned int
+nr_pixblock_get_hash (const NRPixBlock *pb)
+{
+ unsigned int hval;
+ unsigned int width, height, bpp, x, y, c;
+ width = pb->area.x1 - pb->area.x0;
+ height = pb->area.y1 - pb->area.y0;
+ bpp = NR_PIXBLOCK_BPP(pb);
+ hval = pb->mode;
+ hval = (hval << 5) - hval + pb->empty;
+ hval = (hval << 5) - hval + pb->area.x0;
+ hval = (hval << 5) - hval + pb->area.y0;
+ hval = (hval << 5) - hval + pb->area.x1;
+ hval = (hval << 5) - hval + pb->area.y1;
+ for (y = 0; y < height; y++) {
+ const unsigned char *s = NR_PIXBLOCK_ROW(pb, y);
+ for (x = 0; x < width; x++) {
+ for (c = 0; c < bpp; c++) {
+ hval = (hval << 5) - hval + *s++;
+ }
+ }
+ }
+ return hval;
+}
+
+unsigned int
+nr_pixblock_is_equal (const NRPixBlock *a, const NRPixBlock *b)
+{
+ unsigned int width, height, bpp, x, y, c;
+ if (a == b) return 1;
+ if (a->mode != b->mode) return 0;
+ if (a->empty != b->empty) return 0;
+ if (a->area.x0 - b->area.x0) return 0;
+ if (a->area.y0 - b->area.y0) return 0;
+ if (a->area.x1 - b->area.x1) return 0;
+ if (a->area.y1 - b->area.y1) return 0;
+ width = a->area.x1 - a->area.x0;
+ height = a->area.y1 - a->area.y0;
+ bpp = NR_PIXBLOCK_BPP(a);
+ for (y = 0; y < height; y++) {
+ const unsigned char *pa = NR_PIXBLOCK_ROW(a, y);
+ const unsigned char *pb = NR_PIXBLOCK_ROW(b, y);
+ for (x = 0; x < width; x++) {
+ for (c = 0; c < bpp; c++) {
+ if (*pa++ != *pb++) return 0;
+ }
+ }
+ }
+ return 1;
+}
+
/* PixelStore operations */
#define NR_4K_BLOCK 32
diff --git a/src/libnr/nr-pixblock.h b/src/libnr/nr-pixblock.h
index 3b50475..813e67d 100644
--- a/src/libnr/nr-pixblock.h
+++ b/src/libnr/nr-pixblock.h
@@ -10,6 +10,8 @@
* This code is in public domain
*/
+#include <assert.h>
+
#include <libnr/nr-types.h>
#include <libnr/nr-forward.h>
@@ -17,8 +19,10 @@
extern "C" {
#endif
+#define NR_TINY_MAX 64
+
enum {
- NR_PIXBLOCK_SIZE_TINY, /* Fits in (unsigned char *) */
+ NR_PIXBLOCK_SIZE_TINY, /* Fits in pixblock data */
NR_PIXBLOCK_SIZE_4K, /* Pixelstore */
NR_PIXBLOCK_SIZE_16K, /* Pixelstore */
NR_PIXBLOCK_SIZE_64K, /* Pixelstore */
@@ -27,12 +31,14 @@ enum {
};
enum {
- NR_PIXBLOCK_MODE_A8, /* Grayscale */
+ NR_PIXBLOCK_MODE_G8, /* Grayscale or mask */
NR_PIXBLOCK_MODE_R8G8B8, /* 8 bit RGB */
NR_PIXBLOCK_MODE_R8G8B8A8N, /* Normal 8 bit RGBA */
NR_PIXBLOCK_MODE_R8G8B8A8P /* Premultiplied 8 bit RGBA */
};
+// Automatically allocated rowstride is aligned at 4 bytes
+
struct _NRPixBlock {
unsigned int size : 3;
unsigned int mode : 2;
@@ -41,12 +47,14 @@ struct _NRPixBlock {
NRRectS area;
union {
unsigned char *px;
- unsigned char p[sizeof (unsigned char *)];
+ unsigned char p[NR_TINY_MAX];
} data;
};
-#define NR_PIXBLOCK_BPP(pb) (((pb)->mode == NR_PIXBLOCK_MODE_A8) ? 1 : ((pb)->mode == NR_PIXBLOCK_MODE_R8G8B8) ? 3 : 4)
+#define NR_PIXBLOCK_MODE_BPP(m) ((m == NR_PIXBLOCK_MODE_G8) ? 1 : (m == NR_PIXBLOCK_MODE_R8G8B8) ? 3 : 4)
+#define NR_PIXBLOCK_BPP(pb) (((pb)->mode == NR_PIXBLOCK_MODE_G8) ? 1 : ((pb)->mode == NR_PIXBLOCK_MODE_R8G8B8) ? 3 : 4)
#define NR_PIXBLOCK_PX(pb) (((pb)->size == NR_PIXBLOCK_SIZE_TINY) ? (pb)->data.p : (pb)->data.px)
+#define NR_PIXBLOCK_ROW(pb,r) (NR_PIXBLOCK_PX (pb) + (r) * (pb)->rs)
void nr_pixblock_setup (NRPixBlock *pb, int mode, int x0, int y0, int x1, int y1, int clear);
void nr_pixblock_setup_fast (NRPixBlock *pb, int mode, int x0, int y0, int x1, int y1, int clear);
@@ -56,6 +64,18 @@ void nr_pixblock_release (NRPixBlock *pb);
NRPixBlock *nr_pixblock_new (int mode, int x0, int y0, int x1, int y1, int clear);
NRPixBlock *nr_pixblock_free (NRPixBlock *pb);
+/* Helpers */
+
+unsigned int nr_pixblock_has_alpha (const NRPixBlock *pb);
+void nr_pixblock_get_channel_limits (const NRPixBlock *pb, unsigned int minv[], unsigned int maxv[]);
+void nr_pixblock_get_histogram (const NRPixBlock *pb, unsigned int histogram[][256]);
+unsigned int nr_pixblock_get_crc32 (const NRPixBlock *pb);
+NRULongLong nr_pixblock_get_crc64 (const NRPixBlock *pb);
+unsigned int nr_pixblock_get_hash (const NRPixBlock *pb);
+unsigned int nr_pixblock_is_equal (const NRPixBlock *a, const NRPixBlock *b);
+
+/* Memory management */
+
unsigned char *nr_pixelstore_4K_new (int clear, unsigned char val);
void nr_pixelstore_4K_free (unsigned char *px);
unsigned char *nr_pixelstore_16K_new (int clear, unsigned char val);
diff --git a/src/libnr/nr-types.h b/src/libnr/nr-types.h
index 3231255..e6cee77 100644
--- a/src/libnr/nr-types.h
+++ b/src/libnr/nr-types.h
@@ -23,6 +23,7 @@ typedef int16_t NRShort;
typedef uint16_t NRUShort;
typedef int32_t NRLong;
typedef uint32_t NRULong;
+typedef uint64_t NRULongLong;
#else
#ifdef HAVE_NR_CONFIG_H
/* Automake based systems */
@@ -35,6 +36,7 @@ typedef signed short NRShort;
typedef unsigned short NRUShort;
typedef signed int NRLong;
typedef unsigned int NRULong;
+typedef unsigned __int64 NRULongLong;
#endif
#endif
diff --git a/src/libnr/testnr.c b/src/libnr/testnr.c
index 85457ec..66b4c5d 100644
--- a/src/libnr/testnr.c
+++ b/src/libnr/testnr.c
@@ -67,7 +67,7 @@ main (int argc, const char **argv)
/* Masks */
for (i = 0; i < 16; i++) {
int r, b, c;
- nr_pixblock_setup_fast (&m[i], NR_PIXBLOCK_MODE_A8, 0, 0, 64, 64, 0);
+ nr_pixblock_setup_fast (&m[i], NR_PIXBLOCK_MODE_G8, 0, 0, 64, 64, 0);
for (r = 0; r < 64; r++) {
unsigned int q;
unsigned char *p;
diff --git a/src/libnrtype/nr-rasterfont.c b/src/libnrtype/nr-rasterfont.c
index 9aa3c8f..7d032b6 100644
--- a/src/libnrtype/nr-rasterfont.c
+++ b/src/libnrtype/nr-rasterfont.c
@@ -260,7 +260,7 @@ nr_rasterfont_generic_glyph_mask_render (NRRasterFont *rf, unsigned int glyph, N
area.y1 = NRRF_COORD_INT_UPPER (slot->glyph.ig.bbox.y1) + sy;
break;
case NRRF_TYPE_SVP:
- nr_pixblock_setup_extern (&spb, NR_PIXBLOCK_MODE_A8,
+ nr_pixblock_setup_extern (&spb, NR_PIXBLOCK_MODE_G8,
m->area.x0 - sx, m->area.y0 - sy, m->area.x1 - sx, m->area.y1 - sy,
NR_PIXBLOCK_PX (m), m->rs, FALSE, FALSE);
nr_pixblock_render_svp_mask_or (&spb, slot->glyph.sg.svp);
@@ -383,7 +383,7 @@ nr_rasterfont_ensure_glyph_slot (NRRasterFont *rf, unsigned int glyph, unsigned
slot->glyph.ig.bbox.x1 = MIN (x1, 32767);
slot->glyph.ig.bbox.y1 = MIN (y1, 32767);
slot->glyph.ig.px = nr_new (unsigned char, w * h);
- nr_pixblock_setup_extern (&spb, NR_PIXBLOCK_MODE_A8,
+ nr_pixblock_setup_extern (&spb, NR_PIXBLOCK_MODE_G8,
NRRF_COORD_INT_LOWER (x0),
NRRF_COORD_INT_LOWER (y0),
NRRF_COORD_INT_UPPER (x1),
diff --git a/src/widgets/font-selector.c b/src/widgets/font-selector.c
index 0239738..4abd949 100644
--- a/src/widgets/font-selector.c
+++ b/src/widgets/font-selector.c
@@ -594,7 +594,7 @@ sp_font_preview_expose (GtkWidget *widget, GdkEventExpose *event)
y1 = MIN (y0 + 64, event->area.y + event->area.height);
ps = nr_pixelstore_16K_new (TRUE, 0xff);
nr_pixblock_setup_extern (&pb, NR_PIXBLOCK_MODE_R8G8B8, x0, y0, x1, y1, ps, 3 * (x1 - x0), FALSE, FALSE);
- nr_pixblock_setup_fast (&m, NR_PIXBLOCK_MODE_A8, x0, y0, x1, y1, TRUE);
+ nr_pixblock_setup_fast (&m, NR_PIXBLOCK_MODE_G8, x0, y0, x1, y1, TRUE);
pb.empty = FALSE;
for (i = 0; i < len; i++) {
nr_rasterfont_glyph_mask_render (fprev->rfont, glyphs[i], &m, hpos[i] + startx, starty);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]