summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/mutool/examples/draw-device.js2
-rw-r--r--docs/mutool/run.html6
-rw-r--r--include/mupdf/fitz/glyph-cache.h4
-rw-r--r--include/mupdf/fitz/output-pcl.h2
-rw-r--r--include/mupdf/fitz/output-png.h4
-rw-r--r--include/mupdf/fitz/output-pnm.h4
-rw-r--r--include/mupdf/fitz/output-ps.h2
-rw-r--r--include/mupdf/fitz/pixmap.h47
-rw-r--r--include/mupdf/fitz/util.h2
-rw-r--r--platform/gl/gl-font.c2
-rw-r--r--platform/gl/gl-main.c6
-rw-r--r--platform/x11/pdfapp.c4
-rw-r--r--source/fitz/colorspace.c1309
-rw-r--r--source/fitz/draw-affine.c663
-rw-r--r--source/fitz/draw-blend.c162
-rw-r--r--source/fitz/draw-device.c240
-rw-r--r--source/fitz/draw-edge.c13
-rw-r--r--source/fitz/draw-glyph.c10
-rw-r--r--source/fitz/draw-imp.h7
-rw-r--r--source/fitz/draw-mesh.c44
-rw-r--r--source/fitz/draw-paint.c871
-rw-r--r--source/fitz/draw-scale-simple.c63
-rw-r--r--source/fitz/draw-unpack.c42
-rw-r--r--source/fitz/font.c3
-rw-r--r--source/fitz/glyph.c2
-rw-r--r--source/fitz/halftone.c46
-rw-r--r--source/fitz/image.c61
-rw-r--r--source/fitz/load-bmp.c4
-rw-r--r--source/fitz/load-gif.c2
-rw-r--r--source/fitz/load-jpeg.c6
-rw-r--r--source/fitz/load-jpx.c8
-rw-r--r--source/fitz/load-png.c10
-rw-r--r--source/fitz/load-tiff.c4
-rw-r--r--source/fitz/output-cbz.c2
-rw-r--r--source/fitz/output-pcl.c12
-rw-r--r--source/fitz/output-ps.c7
-rw-r--r--source/fitz/output-pwg.c11
-rw-r--r--source/fitz/paint-glyph.h97
-rw-r--r--source/fitz/pixmap.c541
-rw-r--r--source/fitz/svg-device.c2
-rw-r--r--source/fitz/test-device.c65
-rw-r--r--source/fitz/transition.c99
-rw-r--r--source/fitz/util.c16
-rw-r--r--source/pdf/pdf-image.c43
-rw-r--r--source/pdf/pdf-resources.c10
-rw-r--r--source/tools/mudraw.c21
-rw-r--r--source/tools/murun.c9
-rw-r--r--source/tools/pdfextract.c2
48 files changed, 3319 insertions, 1273 deletions
diff --git a/docs/mutool/examples/draw-device.js b/docs/mutool/examples/draw-device.js
index 140fb54b..21a7a65a 100644
--- a/docs/mutool/examples/draw-device.js
+++ b/docs/mutool/examples/draw-device.js
@@ -4,7 +4,7 @@ var font = new Font("Times-Roman");
var image = new Image("example.png");
var path, text;
-var pixmap = new Pixmap(DeviceRGB, [0,0,500,600]);
+var pixmap = new Pixmap(DeviceRGB, [0,0,500,600], false);
pixmap.clear(255);
var device = new DrawDevice(pixmap);
var transform = [2,0,0,2,0,0]
diff --git a/docs/mutool/run.html b/docs/mutool/run.html
index c9ab103e..e82a68bd 100644
--- a/docs/mutool/run.html
+++ b/docs/mutool/run.html
@@ -219,7 +219,7 @@ A pixmap also has a location (x, y) in addition to its size; so that they can ea
tiles of a page.
<dl>
-<dt>new Pixmap(colorspace, bounds)
+<dt>new Pixmap(colorspace, bounds, alpha)
<dd>Create a new pixmap. The pixel data is <b>not</b> initialized; and will contain garbage.
<dt>Pixmap#clear(value)
<dd>Clear the pixels to the specifed value. Pass 255 for white, or undefined for transparent.
@@ -269,8 +269,8 @@ will keep all the graphics required in memory, so will increase the amount of me
<dd>Create an empty display list.
<dt>DisplayList#run(device, transform)
<dd>Play back the recorded device calls onto the device.
-<dt>DisplayList#toPixmap(transform, colorspace, solid)
-<dd>Render display list to a pixmap. If solid is true, it will render to a white background, otherwise transparent.
+<dt>DisplayList#toPixmap(transform, colorspace, alpha)
+<dd>Render display list to a pixmap. If alpha is true, it will render to a transparent background, otherwise white.
</dl>
<dl>
diff --git a/include/mupdf/fitz/glyph-cache.h b/include/mupdf/fitz/glyph-cache.h
index 6a60d7be..e3573356 100644
--- a/include/mupdf/fitz/glyph-cache.h
+++ b/include/mupdf/fitz/glyph-cache.h
@@ -26,8 +26,8 @@ fz_glyph *fz_render_t3_glyph(fz_context *ctx, fz_font *font, int cid, const fz_m
fz_pixmap *fz_render_t3_glyph_pixmap(fz_context *ctx, fz_font *font, int cid, const fz_matrix *trm, fz_colorspace *model, const fz_irect *scissor);
fz_glyph *fz_render_ft_stroked_glyph(fz_context *ctx, fz_font *font, int gid, const fz_matrix *trm, const fz_matrix *ctm, const fz_stroke_state *state);
fz_pixmap *fz_render_ft_stroked_glyph_pixmap(fz_context *ctx, fz_font *font, int gid, const fz_matrix *trm, const fz_matrix *ctm, const fz_stroke_state *state);
-fz_glyph *fz_render_glyph(fz_context *ctx, fz_font*, int, fz_matrix *, fz_colorspace *model, const fz_irect *scissor);
-fz_pixmap *fz_render_glyph_pixmap(fz_context *ctx, fz_font*, int, fz_matrix *, fz_colorspace *model, const fz_irect *scissor);
+fz_glyph *fz_render_glyph(fz_context *ctx, fz_font*, int, fz_matrix *, fz_colorspace *model, const fz_irect *scissor, int alpha);
+fz_pixmap *fz_render_glyph_pixmap(fz_context *ctx, fz_font*, int, fz_matrix *, const fz_irect *scissor);
fz_glyph *fz_render_stroked_glyph(fz_context *ctx, fz_font*, int, fz_matrix *, const fz_matrix *, const fz_stroke_state *stroke, const fz_irect *scissor);
fz_pixmap *fz_render_stroked_glyph_pixmap(fz_context *ctx, fz_font*, int, fz_matrix *, const fz_matrix *, const fz_stroke_state *stroke, const fz_irect *scissor);
void fz_render_t3_glyph_direct(fz_context *ctx, fz_device *dev, fz_font *font, int gid, const fz_matrix *trm, void *gstate, int nestedDepth);
diff --git a/include/mupdf/fitz/output-pcl.h b/include/mupdf/fitz/output-pcl.h
index 7b72c718..053af1e8 100644
--- a/include/mupdf/fitz/output-pcl.h
+++ b/include/mupdf/fitz/output-pcl.h
@@ -107,7 +107,7 @@ typedef struct fz_color_pcl_output_context_s fz_color_pcl_output_context;
fz_color_pcl_output_context *fz_write_color_pcl_header(fz_context *ctx, fz_output *out, int w, int h, int n, int xres, int yres, int pagenum, const fz_pcl_options *options);
-void fz_write_color_pcl_band(fz_context *ctx, fz_output *out, fz_color_pcl_output_context *poc, int w, int h, int n, int band, int bandheight, unsigned char *samples);
+void fz_write_color_pcl_band(fz_context *ctx, fz_output *out, fz_color_pcl_output_context *poc, int w, int h, int n, int stride, int band, int bandheight, unsigned char *samples);
void fz_write_color_pcl_trailer(fz_context *ctx, fz_output *out, fz_color_pcl_output_context *pcoc);
diff --git a/include/mupdf/fitz/output-png.h b/include/mupdf/fitz/output-png.h
index c77f9e5f..337e838d 100644
--- a/include/mupdf/fitz/output-png.h
+++ b/include/mupdf/fitz/output-png.h
@@ -22,8 +22,8 @@ void fz_write_pixmap_as_png(fz_context *ctx, fz_output *out, const fz_pixmap *pi
typedef struct fz_png_output_context_s fz_png_output_context;
-fz_png_output_context *fz_write_png_header(fz_context *ctx, fz_output *out, int w, int h, int n, int savealpha);
-void fz_write_png_band(fz_context *ctx, fz_output *out, fz_png_output_context *poc, int w, int h, int n, int band, int bandheight, unsigned char *samples, int savealpha);
+fz_png_output_context *fz_write_png_header(fz_context *ctx, fz_output *out, int w, int h, int n, int alpha, int savealpha);
+void fz_write_png_band(fz_context *ctx, fz_output *out, fz_png_output_context *poc, int stride, int band, int bandheight, unsigned char *samples);
void fz_write_png_trailer(fz_context *ctx, fz_output *out, fz_png_output_context *poc);
/*
diff --git a/include/mupdf/fitz/output-pnm.h b/include/mupdf/fitz/output-pnm.h
index f45744a2..42259780 100644
--- a/include/mupdf/fitz/output-pnm.h
+++ b/include/mupdf/fitz/output-pnm.h
@@ -14,7 +14,7 @@ void fz_save_pixmap_as_pnm(fz_context *ctx, fz_pixmap *pixmap, char *filename);
void fz_write_pixmap_as_pnm(fz_context *ctx, fz_output *out, fz_pixmap *pixmap);
void fz_write_pnm_header(fz_context *ctx, fz_output *out, int w, int h, int n);
-void fz_write_pnm_band(fz_context *ctx, fz_output *out, int w, int h, int n, int band, int bandheight, unsigned char *p);
+void fz_write_pnm_band(fz_context *ctx, fz_output *out, int w, int h, int n, int stride, int band, int bandheight, unsigned char *p);
/*
fz_save_pixmap_as_pam: Save a pixmap as a PAM image file.
@@ -23,7 +23,7 @@ void fz_save_pixmap_as_pam(fz_context *ctx, fz_pixmap *pixmap, char *filename, i
void fz_write_pixmap_as_pam(fz_context *ctx, fz_output *out, fz_pixmap *pixmap, int savealpha);
void fz_write_pam_header(fz_context *ctx, fz_output *out, int w, int h, int n, int savealpha);
-void fz_write_pam_band(fz_context *ctx, fz_output *out, int w, int h, int n, int band, int bandheight, unsigned char *sp, int savealpha);
+void fz_write_pam_band(fz_context *ctx, fz_output *out, int w, int h, int n, int stride, int band, int bandheight, unsigned char *sp, int savealpha);
/*
fz_save_bitmap_as_pbm: Save a bitmap as a PBM image file.
diff --git a/include/mupdf/fitz/output-ps.h b/include/mupdf/fitz/output-ps.h
index 83fdd607..f9eb6974 100644
--- a/include/mupdf/fitz/output-ps.h
+++ b/include/mupdf/fitz/output-ps.h
@@ -19,7 +19,7 @@ void fz_write_ps_file_header(fz_context *ctx, fz_output *out);
fz_ps_output_context *fz_write_ps_header(fz_context *ctx, fz_output *out, int w, int h, int n, int xres, int yres, int pagenum);
-void fz_write_ps_band(fz_context *ctx, fz_output *out, fz_ps_output_context *psoc, int w, int h, int n, int band, int bandheight, unsigned char *samples);
+void fz_write_ps_band(fz_context *ctx, fz_output *out, fz_ps_output_context *psoc, int w, int h, int n, int stride, int band, int bandheight, unsigned char *samples);
void fz_write_ps_trailer(fz_context *ctx, fz_output *out, fz_ps_output_context *psoc);
diff --git a/include/mupdf/fitz/pixmap.h b/include/mupdf/fitz/pixmap.h
index be8f45ba..33d127ce 100644
--- a/include/mupdf/fitz/pixmap.h
+++ b/include/mupdf/fitz/pixmap.h
@@ -43,10 +43,12 @@ int fz_pixmap_y(fz_context *ctx, fz_pixmap *pix);
h: The height of the pixmap (in pixels)
+ alpha: 0 for no alpha, 1 for alpha.
+
Returns a pointer to the new pixmap. Throws exception on failure to
allocate.
*/
-fz_pixmap *fz_new_pixmap(fz_context *ctx, fz_colorspace *cs, int w, int h);
+fz_pixmap *fz_new_pixmap(fz_context *ctx, fz_colorspace *cs, int w, int h, int alpha);
/*
fz_new_pixmap_with_bbox: Create a pixmap of a given size,
@@ -62,10 +64,12 @@ fz_pixmap *fz_new_pixmap(fz_context *ctx, fz_colorspace *cs, int w, int h);
bbox: Bounding box specifying location/size of created pixmap.
+ alpha: 0 for no alpha, 1 for alpha.
+
Returns a pointer to the new pixmap. Throws exception on failure to
allocate.
*/
-fz_pixmap *fz_new_pixmap_with_bbox(fz_context *ctx, fz_colorspace *colorspace, const fz_irect *bbox);
+fz_pixmap *fz_new_pixmap_with_bbox(fz_context *ctx, fz_colorspace *colorspace, const fz_irect *bbox, int alpha);
/*
fz_new_pixmap_with_data: Create a new pixmap, with it's origin at
@@ -78,12 +82,17 @@ fz_pixmap *fz_new_pixmap_with_bbox(fz_context *ctx, fz_colorspace *colorspace, c
h: The height of the pixmap (in pixels)
+ alpha: 0 for no alpha, 1 for alpha.
+
+ stride: The byte offset from the pixel data in a row to the pixel
+ data in the next row.
+
samples: The data block to keep the samples in.
Returns a pointer to the new pixmap. Throws exception on failure to
allocate.
*/
-fz_pixmap *fz_new_pixmap_with_data(fz_context *ctx, fz_colorspace *colorspace, int w, int h, unsigned char *samples);
+fz_pixmap *fz_new_pixmap_with_data(fz_context *ctx, fz_colorspace *colorspace, int w, int h, int alpha, int stride, unsigned char *samples);
/*
fz_new_pixmap_with_bbox_and_data: Create a pixmap of a given size,
@@ -104,7 +113,7 @@ fz_pixmap *fz_new_pixmap_with_data(fz_context *ctx, fz_colorspace *colorspace, i
Returns a pointer to the new pixmap. Throws exception on failure to
allocate.
*/
-fz_pixmap *fz_new_pixmap_with_bbox_and_data(fz_context *ctx, fz_colorspace *colorspace, const fz_irect *rect, unsigned char *samples);
+fz_pixmap *fz_new_pixmap_with_bbox_and_data(fz_context *ctx, fz_colorspace *colorspace, const fz_irect *rect, int alpha, unsigned char *samples);
/*
fz_keep_pixmap: Take a reference to a pixmap.
@@ -135,11 +144,18 @@ fz_colorspace *fz_pixmap_colorspace(fz_context *ctx, fz_pixmap *pix);
/*
fz_pixmap_components: Return the number of components in a pixmap.
- Returns the number of components. Does not throw exceptions.
+ Returns the number of components (including alpha). Does not throw exceptions.
*/
int fz_pixmap_components(fz_context *ctx, fz_pixmap *pix);
/*
+ fz_pixmap_components: Return the number of components in a pixmap.
+
+ Returns the number of colorants (components, less any alpha). Does not throw exceptions.
+*/
+int fz_pixmap_colorants(fz_context *ctx, fz_pixmap *pix);
+
+/*
fz_pixmap_samples: Returns a pointer to the pixel data of a pixmap.
Returns the pointer. Does not throw exceptions.
@@ -255,9 +271,15 @@ void fz_convert_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src);
w, h: The width and height of the region in pixels.
- n: The number of color components in the image. Always
- includes a separate alpha channel. For mask images n=1, for greyscale
- (plus alpha) images n=2, for rgb (plus alpha) images n=4.
+ n: The number of color components in the image. Includes
+ a separate alpha channel if alpha is set. For mask images
+ n=1, for greyscale (plus alpha) images n=2, for rgb (plus
+ alpha) images n=4.
+
+ stride: The byte offset from the data for any given pixel
+ to the data for the same pixel on the row below.
+
+ alpha: 0 for no alpha, 1 for alpha present.
interpolate: A boolean flag set to non-zero if the image
will be drawn using linear interpolation, or set to zero if
@@ -280,7 +302,8 @@ void fz_convert_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src);
struct fz_pixmap_s
{
fz_storable storable;
- int x, y, w, h, n;
+ int x, y, w, h, n, stride;
+ int alpha;
int interpolate;
int xres, yres;
fz_colorspace *colorspace;
@@ -319,4 +342,10 @@ void fz_md5_pixmap(fz_context *ctx, fz_pixmap *pixmap, unsigned char digest[16])
fz_pixmap *fz_new_pixmap_from_8bpp_data(fz_context *ctx, int x, int y, int w, int h, unsigned char *sp, int span);
fz_pixmap *fz_new_pixmap_from_1bpp_data(fz_context *ctx, int x, int y, int w, int h, unsigned char *sp, int span);
+#ifdef HAVE_VALGRIND
+int fz_valgrind_pixmap(const fz_pixmap *pix);
+#else
+#define fz_valgrind_pixmap(pix) do {} while (0)
+#endif
+
#endif
diff --git a/include/mupdf/fitz/util.h b/include/mupdf/fitz/util.h
index ffc13382..ad8816c0 100644
--- a/include/mupdf/fitz/util.h
+++ b/include/mupdf/fitz/util.h
@@ -20,7 +20,7 @@ fz_display_list *fz_new_display_list_from_page_number(fz_context *ctx, fz_docume
*/
fz_pixmap *fz_new_pixmap_from_page(fz_context *ctx, fz_page *page, const fz_matrix *ctm, fz_colorspace *cs);
fz_pixmap *fz_new_pixmap_from_page_number(fz_context *ctx, fz_document *doc, int number, const fz_matrix *ctm, fz_colorspace *cs);
-fz_pixmap *fz_new_pixmap_from_display_list(fz_context *ctx, fz_display_list *list, const fz_matrix *ctm, fz_colorspace *cs, int opaque);
+fz_pixmap *fz_new_pixmap_from_display_list(fz_context *ctx, fz_display_list *list, const fz_matrix *ctm, fz_colorspace *cs, int alpha);
/*
fz_new_pixmap_from_page_contents: Render the page contents without annotations to an opaque pixmap.
diff --git a/platform/gl/gl-font.c b/platform/gl/gl-font.c
index 58ead8ee..d6e1acc9 100644
--- a/platform/gl/gl-font.c
+++ b/platform/gl/gl-font.c
@@ -159,7 +159,7 @@ static struct glyph *lookup_glyph(fz_font *font, int gid, float *xp, float *yp)
glEnd();
- pixmap = fz_render_glyph_pixmap(ctx, font, gid, &subpix_trm, NULL, NULL);
+ pixmap = fz_render_glyph_pixmap(ctx, font, gid, &subpix_trm, NULL);
w = pixmap->w;
h = pixmap->h;
diff --git a/platform/gl/gl-main.c b/platform/gl/gl-main.c
index 4a40d4ad..cc849a2f 100644
--- a/platform/gl/gl-main.c
+++ b/platform/gl/gl-main.c
@@ -227,7 +227,8 @@ void texture_from_pixmap(struct texture *tex, fz_pixmap *pix)
{
if (tex->w > max_texture_size || tex->h > max_texture_size)
fz_warn(ctx, "texture size (%d x %d) exceeds implementation limit (%d)", tex->w, tex->h, max_texture_size);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex->w, tex->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, pix->samples);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex->w, tex->h, 0, GL_RGB, GL_UNSIGNED_BYTE, pix->samples);
tex->s = 1;
tex->t = 1;
}
@@ -237,8 +238,9 @@ void texture_from_pixmap(struct texture *tex, fz_pixmap *pix)
int h2 = next_power_of_two(tex->h);
if (w2 > max_texture_size || h2 > max_texture_size)
fz_warn(ctx, "texture size (%d x %d) exceeds implementation limit (%d)", w2, h2, max_texture_size);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w2, h2, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, tex->w, tex->h, GL_RGBA, GL_UNSIGNED_BYTE, pix->samples);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, tex->w, tex->h, GL_RGB, GL_UNSIGNED_BYTE, pix->samples);
tex->s = (float)tex->w / w2;
tex->t = (float)tex->h / h2;
}
diff --git a/platform/x11/pdfapp.c b/platform/x11/pdfapp.c
index ab5b2e8d..fd1f6a1a 100644
--- a/platform/x11/pdfapp.c
+++ b/platform/x11/pdfapp.c
@@ -891,7 +891,7 @@ static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repai
else
colorspace = app->colorspace;
app->image = NULL;
- app->image = fz_new_pixmap_with_bbox(app->ctx, colorspace, &ibounds);
+ app->image = fz_new_pixmap_with_bbox(app->ctx, colorspace, &ibounds, 1);
fz_clear_pixmap_with_value(app->ctx, app->image, 255);
if (app->page_list || app->annotations_list)
{
@@ -914,7 +914,7 @@ static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repai
colorspace = fz_device_gray(app->ctx);
else
colorspace = app->colorspace;
- app->image = fz_new_pixmap_with_bbox(app->ctx, colorspace, &ibounds);
+ app->image = fz_new_pixmap_with_bbox(app->ctx, colorspace, &ibounds, app->image->alpha);
app->duration = 0;
new_trans = fz_page_presentation(app->ctx, app->page, &app->duration);
if (new_trans)
diff --git a/source/fitz/colorspace.c b/source/fitz/colorspace.c
index 026953cb..b4d511e8 100644
--- a/source/fitz/colorspace.c
+++ b/source/fitz/colorspace.c
@@ -283,15 +283,74 @@ static void fast_gray_to_rgb(fz_pixmap *dst, fz_pixmap *src)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * (dst->alpha + 3);
+ int s_line_inc = src->stride - w * (src->alpha + 1);
+
+ if (d_line_inc == 0 && s_line_inc == 0)
+ {
+ w *= h;
+ h = 1;
+ }
+
+ if (dst->alpha)
{
- d[0] = s[0];
- d[1] = s[0];
- d[2] = s[0];
- d[3] = s[1];
- s += 2;
- d += 4;
+ if (src->alpha)
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = s[0];
+ d[1] = s[0];
+ d[2] = s[0];
+ d[3] = s[1];
+ s += 2;
+ d += 4;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ else
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = s[0];
+ d[1] = s[0];
+ d[2] = s[0];
+ d[3] = 255;
+ s++;
+ d += 4;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ }
+ else
+ {
+ int si = 1 + src->alpha;
+
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = s[0];
+ d[1] = s[0];
+ d[2] = s[0];
+ s += si;
+ d += 3;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
}
}
@@ -299,16 +358,77 @@ static void fast_gray_to_cmyk(fz_pixmap *dst, fz_pixmap *src)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * (dst->alpha + 4);
+ int s_line_inc = src->stride - w * (src->alpha + 1);
+
+ if (d_line_inc == 0 && s_line_inc == 0)
+ {
+ w *= h;
+ h = 1;
+ }
+
+ if (dst->alpha)
+ {
+ if (src->alpha)
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = 0;
+ d[1] = 0;
+ d[2] = 0;
+ d[3] = 255 - s[0];
+ d[4] = s[1];
+ s += 2;
+ d += 5;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ else
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = 0;
+ d[1] = 0;
+ d[2] = 0;
+ d[3] = 255 - s[0];
+ d[4] = 255;
+ s++;
+ d += 5;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ }
+ else
{
- d[0] = 0;
- d[1] = 0;
- d[2] = 0;
- d[3] = 255 - s[0];
- d[4] = s[1];
- s += 2;
- d += 5;
+ int si = 1 + src->alpha;
+
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = 0;
+ d[1] = 0;
+ d[2] = 0;
+ d[3] = 255 - s[0];
+ s += si;
+ d += 4;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
}
}
@@ -316,13 +436,68 @@ static void fast_rgb_to_gray(fz_pixmap *dst, fz_pixmap *src)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * (dst->alpha + 1);
+ int s_line_inc = src->stride - w * (src->alpha + 3);
+
+ if (d_line_inc == 0 && s_line_inc == 0)
+ {
+ w *= h;
+ h = 1;
+ }
+
+ if (dst->alpha)
+ {
+ if (src->alpha)
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = ((s[0]+1) * 77 + (s[1]+1) * 150 + (s[2]+1) * 28) >> 8;
+ d[1] = s[3];
+ s += 4;
+ d += 2;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ else
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = ((s[0]+1) * 77 + (s[1]+1) * 150 + (s[2]+1) * 28) >> 8;
+ d[1] = 255;
+ s += 3;
+ d += 2;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ }
+ else
{
- d[0] = ((s[0]+1) * 77 + (s[1]+1) * 150 + (s[2]+1) * 28) >> 8;
- d[1] = s[3];
- s += 4;
- d += 2;
+ int sn = src->n;
+
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = ((s[0]+1) * 77 + (s[1]+1) * 150 + (s[2]+1) * 28) >> 8;
+ s += sn;
+ d++;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
}
}
@@ -330,13 +505,68 @@ static void fast_bgr_to_gray(fz_pixmap *dst, fz_pixmap *src)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * (dst->alpha + 1);
+ int s_line_inc = src->stride - w * (src->alpha + 3);
+
+ if (d_line_inc == 0 && s_line_inc == 0)
+ {
+ w *= h;
+ h = 1;
+ }
+
+ if (dst->alpha)
+ {
+ if (src->alpha)
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = ((s[0]+1) * 28 + (s[1]+1) * 150 + (s[2]+1) * 77) >> 8;
+ d[1] = s[3];
+ s += 4;
+ d += 2;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ else
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = ((s[0]+1) * 28 + (s[1]+1) * 150 + (s[2]+1) * 77) >> 8;
+ d[1] = 255;
+ s += 3;
+ d += 2;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ }
+ else
{
- d[0] = ((s[0]+1) * 28 + (s[1]+1) * 150 + (s[2]+1) * 77) >> 8;
- d[1] = s[3];
- s += 4;
- d += 2;
+ int si = 3 + src->alpha;
+
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = ((s[0]+1) * 28 + (s[1]+1) * 150 + (s[2]+1) * 77) >> 8;
+ s += si;
+ d++;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
}
}
@@ -344,20 +574,89 @@ static void fast_rgb_to_cmyk(fz_pixmap *dst, fz_pixmap *src)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * (dst->alpha + 4);
+ int s_line_inc = src->stride - w * (src->alpha + 3);
+
+ if (d_line_inc == 0 && s_line_inc == 0)
+ {
+ w *= h;
+ h = 1;
+ }
+
+ if (dst->alpha)
+ {
+ if (src->alpha)
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ unsigned char c = 255 - s[0];
+ unsigned char m = 255 - s[1];
+ unsigned char y = 255 - s[2];
+ unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y));
+ d[0] = c - k;
+ d[1] = m - k;
+ d[2] = y - k;
+ d[3] = k;
+ d[4] = s[3];
+ s += 4;
+ d += 5;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ else
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ unsigned char c = 255 - s[0];
+ unsigned char m = 255 - s[1];
+ unsigned char y = 255 - s[2];
+ unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y));
+ d[0] = c - k;
+ d[1] = m - k;
+ d[2] = y - k;
+ d[3] = k;
+ d[4] = 255;
+ s += 3;
+ d += 5;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ }
+ else
{
- unsigned char c = 255 - s[0];
- unsigned char m = 255 - s[1];
- unsigned char y = 255 - s[2];
- unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y));
- d[0] = c - k;
- d[1] = m - k;
- d[2] = y - k;
- d[3] = k;
- d[4] = s[3];
- s += 4;
- d += 5;
+ int si = 3 + src->alpha;
+
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ unsigned char c = 255 - s[0];
+ unsigned char m = 255 - s[1];
+ unsigned char y = 255 - s[2];
+ unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y));
+ d[0] = c - k;
+ d[1] = m - k;
+ d[2] = y - k;
+ d[3] = k;
+ s += si;
+ d += 4;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
}
}
@@ -365,20 +664,89 @@ static void fast_bgr_to_cmyk(fz_pixmap *dst, fz_pixmap *src)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * (dst->alpha + 4);
+ int s_line_inc = src->stride - w * (src->alpha + 3);
+
+ if (d_line_inc == 0 && s_line_inc == 0)
{
- unsigned char c = 255 - s[2];
- unsigned char m = 255 - s[1];
- unsigned char y = 255 - s[0];
- unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y));
- d[0] = c - k;
- d[1] = m - k;
- d[2] = y - k;
- d[3] = k;
- d[4] = s[3];
- s += 4;
- d += 5;
+ w *= h;
+ h = 1;
+ }
+
+ if (dst->alpha)
+ {
+ if (src->alpha)
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ unsigned char c = 255 - s[2];
+ unsigned char m = 255 - s[1];
+ unsigned char y = 255 - s[0];
+ unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y));
+ d[0] = c - k;
+ d[1] = m - k;
+ d[2] = y - k;
+ d[3] = k;
+ d[4] = s[3];
+ s += 4;
+ d += 5;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ else
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ unsigned char c = 255 - s[2];
+ unsigned char m = 255 - s[1];
+ unsigned char y = 255 - s[0];
+ unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y));
+ d[0] = c - k;
+ d[1] = m - k;
+ d[2] = y - k;
+ d[3] = k;
+ d[4] = 255;
+ s += 3;
+ d += 5;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ }
+ else
+ {
+ int si = 3 + src->alpha;
+
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ unsigned char c = 255 - s[2];
+ unsigned char m = 255 - s[1];
+ unsigned char y = 255 - s[0];
+ unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y));
+ d[0] = c - k;
+ d[1] = m - k;
+ d[2] = y - k;
+ d[3] = k;
+ s += si;
+ d += 4;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
}
}
@@ -386,16 +754,76 @@ static void fast_cmyk_to_gray(fz_pixmap *dst, fz_pixmap *src)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * (dst->alpha + 1);
+ int s_line_inc = src->stride - w * (src->alpha + 4);
+
+ if (d_line_inc == 0 && s_line_inc == 0)
{
- unsigned char c = fz_mul255(s[0], 77);
- unsigned char m = fz_mul255(s[1], 150);
- unsigned char y = fz_mul255(s[2], 28);
- d[0] = 255 - (unsigned char)fz_mini(c + m + y + s[3], 255);
- d[1] = s[4];
- s += 5;
- d += 2;
+ w *= h;
+ h = 1;
+ }
+
+ if (dst->alpha)
+ {
+ if (src->alpha)
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ unsigned char c = fz_mul255(s[0], 77);
+ unsigned char m = fz_mul255(s[1], 150);
+ unsigned char y = fz_mul255(s[2], 28);
+ d[0] = 255 - (unsigned char)fz_mini(c + m + y + s[3], 255);
+ d[1] = s[4];
+ s += 5;
+ d += 2;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ else
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ unsigned char c = fz_mul255(s[0], 77);
+ unsigned char m = fz_mul255(s[1], 150);
+ unsigned char y = fz_mul255(s[2], 28);
+ d[0] = 255 - (unsigned char)fz_mini(c + m + y + s[3], 255);
+ d[1] = 255;
+ s += 3;
+ d += 2;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ }
+ else
+ {
+ int si = 4 + src->alpha;
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ unsigned char c = fz_mul255(s[0], 77);
+ unsigned char m = fz_mul255(s[1], 150);
+ unsigned char y = fz_mul255(s[2], 28);
+ d[0] = 255 - (unsigned char)fz_mini(c + m + y + s[3], 255);
+ s += si;
+ d++;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
}
}
@@ -592,15 +1020,150 @@ fast_cmyk_to_rgb_ARM(unsigned char *dst, unsigned char *src, int n)
}
#endif
+static inline void cached_cmyk_conv(unsigned char *restrict const pr, unsigned char *restrict const pg, unsigned char *restrict const pb,
+ unsigned int *restrict const C, unsigned int *restrict const M, unsigned int *restrict const Y, unsigned int *restrict const K,
+ unsigned int c, unsigned int m, unsigned int y, unsigned int k)
+{
+#ifdef SLOWCMYK
+ unsigned int r, g, b;
+ unsigned int cm, c1m, cm1, c1m1, c1m1y, c1m1y1, c1my, c1my1, cm1y, cm1y1, cmy, cmy1;
+ unsigned int x0, x1;
+
+ if (c == *C && m == *M && y == *Y && k == *K)
+ {
+ /* Nothing to do */
+ }
+ else if (k == 0 && c == 0 && m == 0 && y == 0)
+ {
+ *pr = *pg = *pb = 255;
+ *C = 0;
+ *M = 0;
+ *Y = 0;
+ *K = 0;
+ }
+ else if (k == 255)
+ {
+ *pr = *pg = *pb = 0;
+ *C = 0;
+ *M = 0;
+ *Y = 0;
+ *K = 255;
+ }
+ else
+ {
+ c += c>>7;
+ m += m>>7;
+ y += y>>7;
+ k += k>>7;
+ y >>= 1; /* Ditch 1 bit of Y to avoid overflow */
+ cm = c * m;
+ c1m = (m<<8) - cm;
+ cm1 = (c<<8) - cm;
+ c1m1 = ((256 - m)<<8) - cm1;
+ c1m1y = c1m1 * y;
+ c1m1y1 = (c1m1<<7) - c1m1y;
+ c1my = c1m * y;
+ c1my1 = (c1m<<7) - c1my;
+ cm1y = cm1 * y;
+ cm1y1 = (cm1<<7) - cm1y;
+ cmy = cm * y;
+ cmy1 = (cm<<7) - cmy;
+
+ /* this is a matrix multiplication, unrolled for performance */
+ x1 = c1m1y1 * k; /* 0 0 0 1 */
+ x0 = (c1m1y1<<8) - x1; /* 0 0 0 0 */
+ x1 = x1>>8; /* From 23 fractional bits to 15 */
+ r = g = b = x0;
+ r += 35 * x1; /* 0.1373 */
+ g += 31 * x1; /* 0.1216 */
+ b += 32 * x1; /* 0.1255 */
+
+ x1 = c1m1y * k; /* 0 0 1 1 */
+ x0 = (c1m1y<<8) - x1; /* 0 0 1 0 */
+ x1 >>= 8; /* From 23 fractional bits to 15 */
+ r += 28 * x1; /* 0.1098 */
+ g += 26 * x1; /* 0.1020 */
+ r += x0;
+ x0 >>= 8; /* From 23 fractional bits to 15 */
+ g += 243 * x0; /* 0.9490 */
+
+ x1 = c1my1 * k; /* 0 1 0 1 */
+ x0 = (c1my1<<8) - x1; /* 0 1 0 0 */
+ x1 >>= 8; /* From 23 fractional bits to 15 */
+ x0 >>= 8; /* From 23 fractional bits to 15 */
+ r += 36 * x1; /* 0.1412 */
+ r += 237 * x0; /* 0.9255 */
+ b += 141 * x0; /* 0.5490 */
+
+ x1 = c1my * k; /* 0 1 1 1 */
+ x0 = (c1my<<8) - x1; /* 0 1 1 0 */
+ x1 >>= 8; /* From 23 fractional bits to 15 */
+ x0 >>= 8; /* From 23 fractional bits to 15 */
+ r += 34 * x1; /* 0.1333 */
+ r += 238 * x0; /* 0.9294 */
+ g += 28 * x0; /* 0.1098 */
+ b += 36 * x0; /* 0.1412 */
+
+ x1 = cm1y1 * k; /* 1 0 0 1 */
+ x0 = (cm1y1<<8) - x1; /* 1 0 0 0 */
+ x1 >>= 8; /* From 23 fractional bits to 15 */
+ x0 >>= 8; /* From 23 fractional bits to 15 */
+ g += 15 * x1; /* 0.0588 */
+ b += 36 * x1; /* 0.1412 */
+ g += 174 * x0; /* 0.6784 */
+ b += 240 * x0; /* 0.9373 */
+
+ x1 = cm1y * k; /* 1 0 1 1 */
+ x0 = (cm1y<<8) - x1; /* 1 0 1 0 */
+ x1 >>= 8; /* From 23 fractional bits to 15 */
+ x0 >>= 8; /* From 23 fractional bits to 15 */
+ g += 19 * x1; /* 0.0745 */
+ g += 167 * x0; /* 0.6510 */
+ b += 80 * x0; /* 0.3137 */
+
+ x1 = cmy1 * k; /* 1 1 0 1 */
+ x0 = (cmy1<<8) - x1; /* 1 1 0 0 */
+ x1 >>= 8; /* From 23 fractional bits to 15 */
+ x0 >>= 8; /* From 23 fractional bits to 15 */
+ b += 2 * x1; /* 0.0078 */
+ r += 46 * x0; /* 0.1804 */
+ g += 49 * x0; /* 0.1922 */
+ b += 147 * x0; /* 0.5725 */
+
+ x0 = cmy * (256-k); /* 1 1 1 0 */
+ x0 >>= 8; /* From 23 fractional bits to 15 */
+ r += 54 * x0; /* 0.2118 */
+ g += 54 * x0; /* 0.2119 */
+ b += 57 * x0; /* 0.2235 */
+
+ r -= (r>>8);
+ g -= (g>>8);
+ b -= (b>>8);
+ *pr = r>>23;
+ *pg = g>>23;
+ *pb = b>>23;
+ *C = c;
+ *M = m;
+ *Y = y;
+ *K = k;
+ }
+#else
+ *pr = 255 - (unsigned char)fz_mini(c + k, 255);
+ *pg = 255 - (unsigned char)fz_mini(m + k, 255);
+ *pb = 255 - (unsigned char)fz_mini(y + k, 255);
+#endif
+}
+
static void fast_cmyk_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- int n = src->w * src->h;
-#ifdef ARCH_ARM
- fast_cmyk_to_rgb_ARM(d, s, n);
-#else
- unsigned int C,M,Y,K,r,g,b;
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * (dst->alpha + 3);
+ int s_line_inc = src->stride - w * (src->alpha + 4);
+ unsigned int C,M,Y,K;
+ unsigned char r,g,b;
C = 0;
M = 0;
@@ -610,174 +1173,169 @@ static void fast_cmyk_to_rgb(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
g = 255;
b = 255;
- while (n--)
+ if (d_line_inc == 0 && s_line_inc == 0)
{
-#ifdef SLOWCMYK
- unsigned int c = s[0];
- unsigned int m = s[1];
- unsigned int y = s[2];
- unsigned int k = s[3];
- unsigned int cm, c1m, cm1, c1m1, c1m1y, c1m1y1, c1my, c1my1, cm1y, cm1y1, cmy, cmy1;
- unsigned int x0, x1;
-
- if (c == C && m == M && y == Y && k == K)
- {
- /* Nothing to do */
- }
- else if (k == 0 && c == 0 && m == 0 && y == 0)
+ w *= h;
+ h = 1;
+ }
+
+ if (dst->alpha)
+ {
+ if (src->alpha)
{
- r = g = b = 255;
- C = 0;
- M = 0;
- Y = 0;
- K = 0;
+#ifdef ARCH_ARM
+ if (h == 1)
+ {
+ fast_cmyk_to_rgb_ARM(d, s, w);
+ return;
+ }
+#endif
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ cached_cmyk_conv(&r, &g, &b, &C, &M, &Y, &K, s[0], s[1], s[2], s[3]);
+ d[0] = r;
+ d[1] = g;
+ d[2] = b;
+ d[3] = s[4];
+ s += 5;
+ d += 4;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
}
- else if (k == 255)
+ else
{
- r = g = b = 0;
- C = 0;
- M = 0;
- Y = 0;
- K = 255;
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ cached_cmyk_conv(&r, &g, &b, &C, &M, &Y, &K, s[0], s[1], s[2], s[3]);
+ d[0] = r;
+ d[1] = g;
+ d[2] = b;
+ d[3] = 255;
+ s += 4;
+ d += 4;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
}
- else
+ }
+ else
+ {
+ /* We shouldn't lose alpha */
+ assert(src->alpha == 0);
+
+ while (h--)
{
- c += c>>7;
- m += m>>7;
- y += y>>7;
- k += k>>7;
- y >>= 1; /* Ditch 1 bit of Y to avoid overflow */
- cm = c * m;
- c1m = (m<<8) - cm;
- cm1 = (c<<8) - cm;
- c1m1 = ((256 - m)<<8) - cm1;
- c1m1y = c1m1 * y;
- c1m1y1 = (c1m1<<7) - c1m1y;
- c1my = c1m * y;
- c1my1 = (c1m<<7) - c1my;
- cm1y = cm1 * y;
- cm1y1 = (cm1<<7) - cm1y;
- cmy = cm * y;
- cmy1 = (cm<<7) - cmy;
-
- /* this is a matrix multiplication, unrolled for performance */
- x1 = c1m1y1 * k; /* 0 0 0 1 */
- x0 = (c1m1y1<<8) - x1; /* 0 0 0 0 */
- x1 = x1>>8; /* From 23 fractional bits to 15 */
- r = g = b = x0;
- r += 35 * x1; /* 0.1373 */
- g += 31 * x1; /* 0.1216 */
- b += 32 * x1; /* 0.1255 */
-
- x1 = c1m1y * k; /* 0 0 1 1 */
- x0 = (c1m1y<<8) - x1; /* 0 0 1 0 */
- x1 >>= 8; /* From 23 fractional bits to 15 */
- r += 28 * x1; /* 0.1098 */
- g += 26 * x1; /* 0.1020 */
- r += x0;
- x0 >>= 8; /* From 23 fractional bits to 15 */
- g += 243 * x0; /* 0.9490 */
-
- x1 = c1my1 * k; /* 0 1 0 1 */
- x0 = (c1my1<<8) - x1; /* 0 1 0 0 */
- x1 >>= 8; /* From 23 fractional bits to 15 */
- x0 >>= 8; /* From 23 fractional bits to 15 */
- r += 36 * x1; /* 0.1412 */
- r += 237 * x0; /* 0.9255 */
- b += 141 * x0; /* 0.5490 */
-
- x1 = c1my * k; /* 0 1 1 1 */
- x0 = (c1my<<8) - x1; /* 0 1 1 0 */
- x1 >>= 8; /* From 23 fractional bits to 15 */
- x0 >>= 8; /* From 23 fractional bits to 15 */
- r += 34 * x1; /* 0.1333 */
- r += 238 * x0; /* 0.9294 */
- g += 28 * x0; /* 0.1098 */
- b += 36 * x0; /* 0.1412 */
-
- x1 = cm1y1 * k; /* 1 0 0 1 */
- x0 = (cm1y1<<8) - x1; /* 1 0 0 0 */
- x1 >>= 8; /* From 23 fractional bits to 15 */
- x0 >>= 8; /* From 23 fractional bits to 15 */
- g += 15 * x1; /* 0.0588 */
- b += 36 * x1; /* 0.1412 */
- g += 174 * x0; /* 0.6784 */
- b += 240 * x0; /* 0.9373 */
-
- x1 = cm1y * k; /* 1 0 1 1 */
- x0 = (cm1y<<8) - x1; /* 1 0 1 0 */
- x1 >>= 8; /* From 23 fractional bits to 15 */
- x0 >>= 8; /* From 23 fractional bits to 15 */
- g += 19 * x1; /* 0.0745 */
- g += 167 * x0; /* 0.6510 */
- b += 80 * x0; /* 0.3137 */
-
- x1 = cmy1 * k; /* 1 1 0 1 */
- x0 = (cmy1<<8) - x1; /* 1 1 0 0 */
- x1 >>= 8; /* From 23 fractional bits to 15 */
- x0 >>= 8; /* From 23 fractional bits to 15 */
- b += 2 * x1; /* 0.0078 */
- r += 46 * x0; /* 0.1804 */
- g += 49 * x0; /* 0.1922 */
- b += 147 * x0; /* 0.5725 */
-
- x0 = cmy * (256-k); /* 1 1 1 0 */
- x0 >>= 8; /* From 23 fractional bits to 15 */
- r += 54 * x0; /* 0.2118 */
- g += 54 * x0; /* 0.2119 */
- b += 57 * x0; /* 0.2235 */
-
- r -= (r>>8);
- g -= (g>>8);
- b -= (b>>8);
- r = r>>23;
- g = g>>23;
- b = b>>23;
- C = c;
- M = m;
- Y = y;
- K = k;
+ int ww = w;
+ while (ww--)
+ {
+ cached_cmyk_conv(&r, &g, &b, &C, &M, &Y, &K, s[0], s[1], s[2], s[3]);
+ d[0] = r;
+ d[1] = g;
+ d[2] = b;
+ s += 4;
+ d += 3;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
}
- d[0] = r;
- d[1] = g;
- d[2] = b;
-#else
- d[0] = 255 - (unsigned char)fz_mini(s[0] + s[3], 255);
- d[1] = 255 - (unsigned char)fz_mini(s[1] + s[3], 255);
- d[2] = 255 - (unsigned char)fz_mini(s[2] + s[3], 255);
-#endif
- d[3] = s[4];
- s += 5;
- d += 4;
}
-#endif
}
static void fast_cmyk_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * (dst->alpha + 3);
+ int s_line_inc = src->stride - w * (src->alpha + 4);
+ unsigned int C,M,Y,K;
+ unsigned char r,g,b;
+
+ C = 0;
+ M = 0;
+ Y = 0;
+ K = 0;
+ r = 255;
+ g = 255;
+ b = 255;
+
+ if (d_line_inc == 0 && s_line_inc == 0)
{
-#ifdef SLOWCMYK
- float cmyk[4], rgb[3];
- cmyk[0] = s[0] / 255.0f;
- cmyk[1] = s[1] / 255.0f;
- cmyk[2] = s[2] / 255.0f;
- cmyk[3] = s[3] / 255.0f;
- cmyk_to_rgb(ctx, NULL, cmyk, rgb);
- d[0] = rgb[2] * 255;
- d[1] = rgb[1] * 255;
- d[2] = rgb[0] * 255;
-#else
- d[0] = 255 - (unsigned char)fz_mini(s[2] + s[3], 255);
- d[1] = 255 - (unsigned char)fz_mini(s[1] + s[3], 255);
- d[2] = 255 - (unsigned char)fz_mini(s[0] + s[3], 255);
-#endif
- d[3] = s[4];
- s += 5;
- d += 4;
+ w *= h;
+ h = 1;
+ }
+
+ if (dst->alpha)
+ {
+ if (src->alpha)
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ cached_cmyk_conv(&r, &g, &b, &C, &M, &Y, &K, s[0], s[1], s[2], s[3]);
+ d[0] = b;
+ d[1] = g;
+ d[2] = r;
+ d[3] = s[4];
+ s += 5;
+ d += 4;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ else
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ cached_cmyk_conv(&r, &g, &b, &C, &M, &Y, &K, s[0], s[1], s[2], s[3]);
+ d[0] = b;
+ d[1] = g;
+ d[2] = r;
+ d[3] = 255;
+ s += 4;
+ d += 4;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+ }
+ }
+ else
+ {
+ /* We shouldn't lose alpha */
+ assert(src->alpha == 0);
+
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ cached_cmyk_conv(&r, &g, &b, &C, &M, &Y, &K, s[0], s[1], s[2], s[3]);
+ d[0] = b;
+ d[1] = g;
+ d[2] = r;
+ s += 4;
+ d += 3;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
}
}
@@ -785,15 +1343,69 @@ static void fast_rgb_to_bgr(fz_pixmap *dst, fz_pixmap *src)
{
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * (dst->alpha + 3);
+ int s_line_inc = src->stride - w * (src->alpha + 3);
+
+ if (d_line_inc == 0 && s_line_inc == 0)
+ {
+ w *= h;
+ h = 1;
+ }
+
+ if (dst->alpha)
+ {
+ if (src->alpha)
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = s[2];
+ d[1] = s[1];
+ d[2] = s[0];
+ d[3] = s[3];
+ s += 4;
+ d += 4;
+ }
+ }
+ }
+ else
+ {
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = s[2];
+ d[1] = s[1];
+ d[2] = s[0];
+ d[3] = 255;
+ s += 3;
+ d += 4;
+ }
+ }
+ }
+ }
+ else
{
- d[0] = s[2];
- d[1] = s[1];
- d[2] = s[0];
- d[3] = s[3];
- s += 4;
- d += 4;
+ /* We shouldn't lose alpha */
+ assert(src->alpha == 0);
+
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ d[0] = s[2];
+ d[1] = s[1];
+ d[2] = s[0];
+ s += 3;
+ d += 3;
+ }
+ }
}
}
@@ -804,7 +1416,12 @@ fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
float dstv[FZ_MAX_COLORS];
int srcn, dstn;
int k, i;
- unsigned int xy;
+ int w = src->w;
+ int h = src->h;
+ int d_line_inc = dst->stride - w * dst->n;
+ int s_line_inc = src->stride - w * src->n;
+ int da = dst->alpha;
+ int sa = src->alpha;
fz_colorspace *ss = src->colorspace;
fz_colorspace *ds = dst->colorspace;
@@ -812,14 +1429,18 @@ fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
unsigned char *s = src->samples;
unsigned char *d = dst->samples;
- assert(src->w == dst->w && src->h == dst->h);
- assert(src->n == ss->n + 1);
- assert(dst->n == ds->n + 1);
-
srcn = ss->n;
dstn = ds->n;
- xy = (unsigned int)(src->w * src->h);
+ assert(src->w == dst->w && src->h == dst->h);
+ assert(src->n == srcn + sa);
+ assert(dst->n == dstn + da);
+
+ if (d_line_inc == 0 && s_line_inc == 0)
+ {
+ w *= h;
+ h = 1;
+ }
/* Special case for Lab colorspace (scaling of components to float) */
if (!strcmp(ss->name, "Lab") && srcn == 3)
@@ -827,38 +1448,52 @@ fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
fz_color_converter cc;
fz_lookup_color_converter(ctx, &cc, ds, ss);
- for (; xy > 0; xy--)
+ while (h--)
{
- srcv[0] = *s++ / 255.0f * 100;
- srcv[1] = *s++ - 128;
- srcv[2] = *s++ - 128;
-
- cc.convert(ctx, &cc, dstv, srcv);
+ int ww = w;
+ while (ww--)
+ {
+ srcv[0] = *s++ / 255.0f * 100;
+ srcv[1] = *s++ - 128;
+ srcv[2] = *s++ - 128;
- for (k = 0; k < dstn; k++)
- *d++ = dstv[k] * 255;
+ cc.convert(ctx, &cc, dstv, srcv);
- *d++ = *s++;
+ for (k = 0; k < dstn; k++)
+ *d++ = dstv[k] * 255;
+ if (da)
+ *d++ = (sa ? *s : 255);
+ s += sa;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
}
}
/* Brute-force for small images */
- else if (xy < 256)
+ else if (w*h < 256)
{
fz_color_converter cc;
fz_lookup_color_converter(ctx, &cc, ds, ss);
- for (; xy > 0; xy--)
+ while (h--)
{
- for (k = 0; k < srcn; k++)
- srcv[k] = *s++ / 255.0f;
-
- cc.convert(ctx, &cc, dstv, srcv);
+ int ww = w;
+ while (ww--)
+ {
+ for (k = 0; k < srcn; k++)
+ srcv[k] = *s++ / 255.0f;
- for (k = 0; k < dstn; k++)
- *d++ = dstv[k] * 255;
+ cc.convert(ctx, &cc, dstv, srcv);
- *d++ = *s++;
+ for (k = 0; k < dstn; k++)
+ *d++ = dstv[k] * 255;
+ if (da)
+ *d++ = (sa ? *s : 255);
+ s += sa;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
}
}
@@ -877,12 +1512,20 @@ fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
lookup[i * dstn + k] = dstv[k] * 255;
}
- for (; xy > 0; xy--)
+ while (h--)
{
- i = *s++;
- for (k = 0; k < dstn; k++)
- *d++ = lookup[i * dstn + k];
- *d++ = *s++;
+ int ww = w;
+ while (ww--)
+ {
+ i = *s++;
+ for (k = 0; k < dstn; k++)
+ *d++ = lookup[i * dstn + k];
+ if (da)
+ *d++ = (sa ? *s : 255);
+ s += sa;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
}
}
@@ -893,57 +1536,109 @@ fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
unsigned char *color;
unsigned char dummy = s[0] ^ 255;
unsigned char *sold = &dummy;
+ unsigned char *dold;
fz_color_converter cc;
fz_lookup_color_converter(ctx, &cc, ds, ss);
lookup = fz_new_hash_table(ctx, 509, srcn, -1);
- for (; xy > 0; xy--)
+ while (h--)
{
- if (*s == *sold && memcmp(sold,s,srcn) == 0)
- {
- sold = s;
- memcpy(d, d-dstn-1, dstn);
- d += dstn;
- s += srcn;
- *d++ = *s++;
- }
- else
+ int ww = w;
+ while (ww--)
{
- sold = s;
- color = fz_hash_find(ctx, lookup, s);
- if (color)
+ if (*s == *sold && memcmp(sold,s,srcn) == 0)
{
- memcpy(d, color, dstn);
- s += srcn;
+ sold = s;
+ memcpy(d, dold, dstn);
d += dstn;
- *d++ = *s++;
+ s += srcn;
+ if (da)
+ *d++ = (sa ? *s : 255);
+ s += sa;
}
else
{
- for (k = 0; k < srcn; k++)
- srcv[k] = *s++ / 255.0f;
- cc.convert(ctx, &cc, dstv, srcv);
- for (k = 0; k < dstn; k++)
- *d++ = dstv[k] * 255;
-
- fz_hash_insert(ctx, lookup, s - srcn, d - dstn);
-
- *d++ = *s++;
+ sold = s;
+ dold = d;
+ color = fz_hash_find(ctx, lookup, s);
+ if (color)
+ {
+ memcpy(d, color, dstn);
+ s += srcn;
+ d += dstn;
+ if (dst->alpha)
+ *d++ = (sa ? *s : 255);
+ s += sa;
+ }
+ else
+ {
+ for (k = 0; k < srcn; k++)
+ srcv[k] = *s++ / 255.0f;
+ cc.convert(ctx, &cc, dstv, srcv);
+ for (k = 0; k < dstn; k++)
+ *d++ = dstv[k] * 255;
+
+ fz_hash_insert(ctx, lookup, s - srcn, d - dstn);
+
+ if (dst->alpha)
+ *d++ = (sa ? *s : 255);
+ s += sa;
+ }
}
}
+ d += d_line_inc;
+ s += s_line_inc;
}
fz_drop_hash(ctx, lookup);
}
}
+static void fast_copy_alpha(fz_pixmap *dst, fz_pixmap *src)
+{
+ unsigned char *s = src->samples;
+ unsigned char *d = dst->samples;
+ int w = src->w;
+ int h = src->h;
+ int n = src->n;
+ int d_line_inc = dst->stride - w * dst->n;
+ int s_line_inc = src->stride - w * src->n;
+
+ assert(dst->alpha && src->alpha && dst->n == 1);
+
+ if (d_line_inc == 0 && s_line_inc == 0)
+ {
+ w *= h;
+ h = 1;
+ }
+
+ s += n-1;
+ while (h--)
+ {
+ int ww = w;
+ while (ww--)
+ {
+ *d++ = *s;
+ s += n;
+ }
+ d += d_line_inc;
+ s += s_line_inc;
+ }
+}
+
void
fz_convert_pixmap(fz_context *ctx, fz_pixmap *dp, fz_pixmap *sp)
{
fz_colorspace *ss = sp->colorspace;
fz_colorspace *ds = dp->colorspace;
+ if (ds == NULL && sp->alpha)
+ {
+ fast_copy_alpha(dp, sp);
+ return;
+ }
+
assert(ss && ds);
dp->interpolate = sp->interpolate;
@@ -993,6 +1688,11 @@ std_conv_color(fz_context *ctx, fz_color_converter *cc, float *dstv, const float
fz_colorspace *srcs = cc->ss;
fz_colorspace *dsts = cc->ds;
+ if (srcs == NULL)
+ srcs = fz_device_rgb(ctx);
+ if (dsts == NULL)
+ dsts = fz_device_rgb(ctx);
+
if (srcs != dsts)
{
assert(srcs->to_rgb && dsts->from_rgb);
@@ -1238,6 +1938,7 @@ fz_expand_indexed_pixmap(fz_context *ctx, fz_pixmap *src)
int y, x, k, n, high;
unsigned char *lookup;
fz_irect bbox;
+ int s_line_inc, d_line_inc;
assert(src->colorspace->to_rgb == indexed_to_rgb);
assert(src->n == 2);
@@ -1247,20 +1948,42 @@ fz_expand_indexed_pixmap(fz_context *ctx, fz_pixmap *src)
lookup = idx->lookup;
n = idx->base->n;
- dst = fz_new_pixmap_with_bbox(ctx, idx->base, fz_pixmap_bbox(ctx, src, &bbox));
+ dst = fz_new_pixmap_with_bbox(ctx, idx->base, fz_pixmap_bbox(ctx, src, &bbox), src->alpha);
s = src->samples;
d = dst->samples;
+ s_line_inc = src->stride - src->w * src->n;
+ d_line_inc = dst->stride - dst->w * dst->n;
- for (y = 0; y < src->h; y++)
+ if (src->alpha)
+ {
+ for (y = 0; y < src->h; y++)
+ {
+ for (x = 0; x < src->w; x++)
+ {
+ int v = *s++;
+ int a = *s++;
+ v = fz_mini(v, high);
+ for (k = 0; k < n; k++)
+ *d++ = fz_mul255(lookup[v * n + k], a);
+ *d++ = a;
+ }
+ s += s_line_inc;
+ d += d_line_inc;
+ }
+ }
+ else
{
- for (x = 0; x < src->w; x++)
+ for (y = 0; y < src->h; y++)
{
- int v = *s++;
- int a = *s++;
- v = fz_mini(v, high);
- for (k = 0; k < n; k++)
- *d++ = fz_mul255(lookup[v * n + k], a);
- *d++ = a;
+ for (x = 0; x < src->w; x++)
+ {
+ int v = *s++;
+ v = fz_mini(v, high);
+ for (k = 0; k < n; k++)
+ *d++ = lookup[v * n + k];
+ }
+ s += s_line_inc;
+ d += d_line_inc;
}
}
diff --git a/source/fitz/draw-affine.c b/source/fitz/draw-affine.c
index 068878cc..e4db9ec8 100644
--- a/source/fitz/draw-affine.c
+++ b/source/fitz/draw-affine.c
@@ -13,22 +13,21 @@ static inline int bilerp(int a, int b, int c, int d, int u, int v)
return lerp(lerp(a, b, u), lerp(c, d, u), v);
}
-static inline byte *sample_nearest(byte *s, int w, int h, int n, int u, int v)
+static inline byte *sample_nearest(byte *s, int w, int h, int str, int n, int u, int v)
{
if (u < 0) u = 0;
if (v < 0) v = 0;
if (u >= (w>>16)) u = (w>>16) - 1;
if (v >= (h>>16)) v = (h>>16) - 1;
- return s + (v * (w>>16) + u) * n;
+ return s + v * str + u * n;
}
/* Blend premultiplied source image in constant alpha over destination */
static inline void
-fz_paint_affine_alpha_N_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha, byte *hp)
+fz_paint_affine_alpha_N_lerp(byte *dp, int da, byte *sp, int sw, int sh, int ss, int sa, int u, int v, int fa, int fb, int w, int n1, int alpha, byte *hp)
{
int k;
- int n1 = n-1;
while (w--)
{
@@ -38,11 +37,11 @@ fz_paint_affine_alpha_N_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, i
int vi = v >> 16;
int uf = u & 0xffff;
int vf = v & 0xffff;
- byte *a = sample_nearest(sp, sw, sh, n, ui, vi);
- byte *b = sample_nearest(sp, sw, sh, n, ui+1, vi);
- byte *c = sample_nearest(sp, sw, sh, n, ui, vi+1);
- byte *d = sample_nearest(sp, sw, sh, n, ui+1, vi+1);
- int xa = bilerp(a[n1], b[n1], c[n1], d[n1], uf, vf);
+ byte *a = sample_nearest(sp, sw, sh, ss, n1+sa, ui, vi);
+ byte *b = sample_nearest(sp, sw, sh, ss, n1+sa, ui+1, vi);
+ byte *c = sample_nearest(sp, sw, sh, ss, n1+sa, ui, vi+1);
+ byte *d = sample_nearest(sp, sw, sh, ss, n1+sa, ui+1, vi+1);
+ int xa = sa ? bilerp(a[n1], b[n1], c[n1], d[n1], uf, vf) : 255;
int t;
xa = fz_mul255(xa, alpha);
t = 255 - xa;
@@ -51,11 +50,12 @@ fz_paint_affine_alpha_N_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, i
int x = bilerp(a[k], b[k], c[k], d[k], uf, vf);
dp[k] = fz_mul255(x, alpha) + fz_mul255(dp[k], t);
}
- dp[n1] = xa + fz_mul255(dp[n1], t);
+ if (da)
+ dp[n1] = xa + fz_mul255(dp[n1], t);
if (hp)
hp[0] = xa + fz_mul255(hp[0], t);
}
- dp += n;
+ dp += n1+da;
if (hp)
hp++;
u += fa;
@@ -65,7 +65,7 @@ fz_paint_affine_alpha_N_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, i
/* Special case code for gray -> rgb */
static inline void
-fz_paint_affine_alpha_g2rgb_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int alpha, byte *hp)
+fz_paint_affine_alpha_g2rgb_lerp(byte *dp, int da, byte *sp, int sw, int sh, int ss, int sa, int u, int v, int fa, int fb, int w, int alpha, byte *hp)
{
while (w--)
{
@@ -75,11 +75,11 @@ fz_paint_affine_alpha_g2rgb_lerp(byte *dp, byte *sp, int sw, int sh, int u, int
int vi = v >> 16;
int uf = u & 0xffff;
int vf = v & 0xffff;
- byte *a = sample_nearest(sp, sw, sh, 2, ui, vi);
- byte *b = sample_nearest(sp, sw, sh, 2, ui+1, vi);
- byte *c = sample_nearest(sp, sw, sh, 2, ui, vi+1);
- byte *d = sample_nearest(sp, sw, sh, 2, ui+1, vi+1);
- int y = bilerp(a[1], b[1], c[1], d[1], uf, vf);
+ byte *a = sample_nearest(sp, sw, sh, ss, 1+sa, ui, vi);
+ byte *b = sample_nearest(sp, sw, sh, ss, 1+sa, ui+1, vi);
+ byte *c = sample_nearest(sp, sw, sh, ss, 1+sa, ui, vi+1);
+ byte *d = sample_nearest(sp, sw, sh, ss, 1+sa, ui+1, vi+1);
+ int y = (sa ? bilerp(a[1], b[1], c[1], d[1], uf, vf) : 255);
int x = bilerp(a[0], b[0], c[0], d[0], uf, vf);
int t;
x = fz_mul255(x, alpha);
@@ -88,7 +88,8 @@ fz_paint_affine_alpha_g2rgb_lerp(byte *dp, byte *sp, int sw, int sh, int u, int
dp[0] = x + fz_mul255(dp[0], t);
dp[1] = x + fz_mul255(dp[1], t);
dp[2] = x + fz_mul255(dp[2], t);
- dp[3] = y + fz_mul255(dp[3], t);
+ if (da)
+ dp[3] = y + fz_mul255(dp[3], t);
if (hp)
hp[0] = y + fz_mul255(hp[0], t);
}
@@ -101,33 +102,32 @@ fz_paint_affine_alpha_g2rgb_lerp(byte *dp, byte *sp, int sw, int sh, int u, int
}
static inline void
-fz_paint_affine_alpha_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha, byte *hp)
+fz_paint_affine_alpha_N_near(byte *dp, int da, byte *sp, int sw, int sh, int ss, int sa, int u, int v, int fa, int fb, int w, int n1, int alpha, byte *hp)
{
int k;
- int n1 = n-1;
if (fa == 0)
{
int ui = u >> 16;
if (ui < 0 || ui >= sw)
return;
- sp += ui * n;
- sw *= n;
+ sp += ui * (n1+sa);
while (w--)
{
int vi = v >> 16;
if (vi >= 0 && vi < sh)
{
- byte *sample = sp + (vi * sw);
- int a = fz_mul255(sample[n-1], alpha);
+ byte *sample = sp + (vi * ss);
+ int a = (sa ? fz_mul255(sample[n1], alpha) : 255);
int t = 255 - a;
for (k = 0; k < n1; k++)
dp[k] = fz_mul255(sample[k], alpha) + fz_mul255(dp[k], t);
- dp[n1] = a + fz_mul255(dp[n1], t);
+ if (da)
+ dp[n1] = a + fz_mul255(dp[n1], t);
if (hp)
hp[0] = a + fz_mul255(hp[0], t);
}
- dp += n;
+ dp += n1+da;
if (hp)
hp++;
v += fb;
@@ -138,22 +138,23 @@ fz_paint_affine_alpha_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, i
int vi = v >> 16;
if (vi < 0 || vi >= sh)
return;
- sp += vi * sw * n;
+ sp += vi * ss;
while (w--)
{
int ui = u >> 16;
if (ui >= 0 && ui < sw)
{
- byte *sample = sp + (ui * n);
- int a = fz_mul255(sample[n-1], alpha);
+ byte *sample = sp + (ui * (n1+sa));
+ int a = (sa ? fz_mul255(sample[n1], alpha) : 255);
int t = 255 - a;
for (k = 0; k < n1; k++)
dp[k] = fz_mul255(sample[k], alpha) + fz_mul255(dp[k], t);
- dp[n1] = a + fz_mul255(dp[n1], t);
+ if (da)
+ dp[n1] = a + fz_mul255(dp[n1], t);
if (hp)
hp[0] = a + fz_mul255(hp[0], t);
}
- dp += n;
+ dp += n1+da;
if (hp)
hp++;
u += fa;
@@ -167,16 +168,17 @@ fz_paint_affine_alpha_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, i
int vi = v >> 16;
if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
{
- byte *sample = sp + ((vi * sw + ui) * n);
- int a = fz_mul255(sample[n-1], alpha);
+ byte *sample = sp + (vi * ss) + (ui * (n1+sa));
+ int a = (sa ? fz_mul255(sample[n1], alpha) : 255);
int t = 255 - a;
for (k = 0; k < n1; k++)
dp[k] = fz_mul255(sample[k], alpha) + fz_mul255(dp[k], t);
- dp[n1] = a + fz_mul255(dp[n1], t);
+ if (da)
+ dp[n1] = a + fz_mul255(dp[n1], t);
if (hp)
hp[0] = a + fz_mul255(hp[0], t);
}
- dp += n;
+ dp += n1+da;
if (hp)
hp++;
u += fa;
@@ -186,32 +188,32 @@ fz_paint_affine_alpha_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, i
}
static inline void
-fz_paint_affine_alpha_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int alpha, byte *hp)
+fz_paint_affine_alpha_g2rgb_near(byte *dp, int da, byte *sp, int sw, int sh, int ss, int sa, int u, int v, int fa, int fb, int w, int alpha, byte *hp)
{
if (fa == 0)
{
int ui = u >> 16;
if (ui < 0 || ui >= sw)
return;
- sp += ui * 2;
- sw *= 2;
+ sp += ui * (1+sa);
while (w--)
{
int vi = v >> 16;
if (vi >= 0 && vi < sh)
{
- byte *sample = sp + (vi * sw);
+ byte *sample = sp + (vi * ss);
int x = fz_mul255(sample[0], alpha);
- int a = fz_mul255(sample[1], alpha);
+ int a = (sa ? fz_mul255(sample[1], alpha) : 255);
int t = 255 - a;
dp[0] = x + fz_mul255(dp[0], t);
dp[1] = x + fz_mul255(dp[1], t);
dp[2] = x + fz_mul255(dp[2], t);
- dp[3] = a + fz_mul255(dp[3], t);
+ if (da)
+ dp[3] = a + fz_mul255(dp[3], t);
if (hp)
hp[0] = a + fz_mul255(hp[0], t);
}
- dp += 4;
+ dp += 3 + da;
if (hp)
hp++;
v += fb;
@@ -222,24 +224,25 @@ fz_paint_affine_alpha_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int
int vi = v >> 16;
if (vi < 0 || vi >= sh)
return;
- sp += vi * sw * 2;
+ sp += vi * ss;
while (w--)
{
int ui = u >> 16;
if (ui >= 0 && ui < sw)
{
- byte *sample = sp + (ui * 2);
+ byte *sample = sp + (ui * (1+sa));
int x = fz_mul255(sample[0], alpha);
- int a = fz_mul255(sample[1], alpha);
+ int a = (sa ? fz_mul255(sample[1], alpha) : 255);
int t = 255 - a;
dp[0] = x + fz_mul255(dp[0], t);
dp[1] = x + fz_mul255(dp[1], t);
dp[2] = x + fz_mul255(dp[2], t);
- dp[3] = a + fz_mul255(dp[3], t);
+ if (da)
+ dp[3] = a + fz_mul255(dp[3], t);
if (hp)
hp[0] = a + fz_mul255(hp[0], t);
}
- dp += 4;
+ dp += 3 + da;
if (hp)
hp++;
u += fa;
@@ -253,18 +256,19 @@ fz_paint_affine_alpha_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int
int vi = v >> 16;
if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
{
- byte *sample = sp + ((vi * sw + ui) * 2);
+ byte *sample = sp + (vi * ss) + (ui * (1+sa));
int x = fz_mul255(sample[0], alpha);
- int a = fz_mul255(sample[1], alpha);
+ int a = (sa ? fz_mul255(sample[1], alpha): 255);
int t = 255 - a;
dp[0] = x + fz_mul255(dp[0], t);
dp[1] = x + fz_mul255(dp[1], t);
dp[2] = x + fz_mul255(dp[2], t);
- dp[3] = a + fz_mul255(dp[3], t);
+ if (da)
+ dp[3] = a + fz_mul255(dp[3], t);
if (hp)
hp[0] = a + fz_mul255(hp[0], t);
}
- dp += 4;
+ dp += 3 + da;
if (hp)
hp++;
u += fa;
@@ -276,10 +280,9 @@ fz_paint_affine_alpha_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int
/* Blend premultiplied source image over destination */
static inline void
-fz_paint_affine_N_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, byte *hp)
+fz_paint_affine_N_lerp(byte *dp, int da, byte *sp, int sw, int sh, int ss, int sa, int u, int v, int fa, int fb, int w, int n1, byte *hp)
{
int k;
- int n1 = n-1;
while (w--)
{
@@ -289,22 +292,23 @@ fz_paint_affine_N_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa,
int vi = v >> 16;
int uf = u & 0xffff;
int vf = v & 0xffff;
- byte *a = sample_nearest(sp, sw, sh, n, ui, vi);
- byte *b = sample_nearest(sp, sw, sh, n, ui+1, vi);
- byte *c = sample_nearest(sp, sw, sh, n, ui, vi+1);
- byte *d = sample_nearest(sp, sw, sh, n, ui+1, vi+1);
- int y = bilerp(a[n1], b[n1], c[n1], d[n1], uf, vf);
+ byte *a = sample_nearest(sp, sw, sh, ss, n1+sa, ui, vi);
+ byte *b = sample_nearest(sp, sw, sh, ss, n1+sa, ui+1, vi);
+ byte *c = sample_nearest(sp, sw, sh, ss, n1+sa, ui, vi+1);
+ byte *d = sample_nearest(sp, sw, sh, ss, n1+sa, ui+1, vi+1);
+ int y = sa ? bilerp(a[n1], b[n1], c[n1], d[n1], uf, vf) : 255;
int t = 255 - y;
for (k = 0; k < n1; k++)
{
int x = bilerp(a[k], b[k], c[k], d[k], uf, vf);
dp[k] = x + fz_mul255(dp[k], t);
}
- dp[n1] = y + fz_mul255(dp[n1], t);
+ if (da)
+ dp[n1] = y + fz_mul255(dp[n1], t);
if (hp)
hp[0] = y + fz_mul255(hp[0], t);
}
- dp += n;
+ dp += n1 + da;
if (hp)
hp++;
u += fa;
@@ -313,7 +317,7 @@ fz_paint_affine_N_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa,
}
static inline void
-fz_paint_affine_solid_g2rgb_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, byte *hp)
+fz_paint_affine_solid_g2rgb_lerp(byte *dp, int da, byte *sp, int sw, int sh, int ss, int sa, int u, int v, int fa, int fb, int w, byte *hp)
{
while (w--)
{
@@ -323,21 +327,22 @@ fz_paint_affine_solid_g2rgb_lerp(byte *dp, byte *sp, int sw, int sh, int u, int
int vi = v >> 16;
int uf = u & 0xffff;
int vf = v & 0xffff;
- byte *a = sample_nearest(sp, sw, sh, 2, ui, vi);
- byte *b = sample_nearest(sp, sw, sh, 2, ui+1, vi);
- byte *c = sample_nearest(sp, sw, sh, 2, ui, vi+1);
- byte *d = sample_nearest(sp, sw, sh, 2, ui+1, vi+1);
- int y = bilerp(a[1], b[1], c[1], d[1], uf, vf);
+ byte *a = sample_nearest(sp, sw, sh, ss, 1+sa, ui, vi);
+ byte *b = sample_nearest(sp, sw, sh, ss, 1+sa, ui+1, vi);
+ byte *c = sample_nearest(sp, sw, sh, ss, 1+sa, ui, vi+1);
+ byte *d = sample_nearest(sp, sw, sh, ss, 1+sa, ui+1, vi+1);
+ int y = (sa ? bilerp(a[1], b[1], c[1], d[1], uf, vf) : 255);
int t = 255 - y;
int x = bilerp(a[0], b[0], c[0], d[0], uf, vf);
dp[0] = x + fz_mul255(dp[0], t);
dp[1] = x + fz_mul255(dp[1], t);
dp[2] = x + fz_mul255(dp[2], t);
- dp[3] = y + fz_mul255(dp[3], t);
+ if (da)
+ dp[3] = y + fz_mul255(dp[3], t);
if (hp)
hp[0] = y + fz_mul255(hp[0], t);
}
- dp += 4;
+ dp += 3 + da;
if (hp)
hp++;
u += fa;
@@ -346,32 +351,30 @@ fz_paint_affine_solid_g2rgb_lerp(byte *dp, byte *sp, int sw, int sh, int u, int
}
static inline void
-fz_paint_affine_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, byte *hp)
+fz_paint_affine_N_near(byte *dp, int da, byte *sp, int sw, int sh, int ss, int sa, int u, int v, int fa, int fb, int w, int n1, byte *hp)
{
int k;
- int n1 = n-1;
if (fa == 0)
{
int ui = u >> 16;
if (ui < 0 || ui >= sw)
return;
- sp += ui*n;
- sw *= n;
+ sp += ui*(n1+sa);
while (w--)
{
int vi = v >> 16;
if (vi >= 0 && vi < sh)
{
- byte *sample = sp + (vi * sw);
- int a = sample[n1];
+ byte *sample = sp + (vi * ss);
+ int a = (sa ? sample[n1] : 255);
/* If a is 0, then sample[k] = 0 for all k, as premultiplied */
if (a != 0)
{
int t = 255 - a;
if (t == 0)
{
- if (n == 4)
+ if (n1+da == 4)
{
*(int *)dp = *(int *)sample;
}
@@ -379,7 +382,8 @@ fz_paint_affine_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa,
{
for (k = 0; k < n1; k++)
dp[k] = sample[k];
- dp[n1] = a;
+ if (da)
+ dp[n1] = a;
}
if (hp)
hp[0] = a;
@@ -388,13 +392,14 @@ fz_paint_affine_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa,
{
for (k = 0; k < n1; k++)
dp[k] = sample[k] + fz_mul255(dp[k], t);
- dp[n1] = a + fz_mul255(dp[n1], t);
+ if (da)
+ dp[n1] = a + fz_mul255(dp[n1], t);
if (hp)
hp[0] = a + fz_mul255(hp[0], t);
}
}
}
- dp += n;
+ dp += n1+da;
if (hp)
hp++;
v += fb;
@@ -405,21 +410,21 @@ fz_paint_affine_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa,
int vi = v >> 16;
if (vi < 0 || vi >= sh)
return;
- sp += vi * sw * n;
+ sp += vi * ss;
while (w--)
{
int ui = u >> 16;
if (ui >= 0 && ui < sw)
{
- byte *sample = sp + (ui * n);
- int a = sample[n1];
+ byte *sample = sp + (ui * (n1+sa));
+ int a = sa ? sample[n1] : 255;
/* If a is 0, then sample[k] = 0 for all k, as premultiplied */
if (a != 0)
{
int t = 255 - a;
if (t == 0)
{
- if (n == 4)
+ if (n1+da == 4)
{
*(int *)dp = *(int *)sample;
}
@@ -427,7 +432,8 @@ fz_paint_affine_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa,
{
for (k = 0; k < n1; k++)
dp[k] = sample[k];
- dp[n1] = a;
+ if (da)
+ dp[n1] = a;
}
if (hp)
hp[0] = a;
@@ -436,13 +442,14 @@ fz_paint_affine_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa,
{
for (k = 0; k < n1; k++)
dp[k] = sample[k] + fz_mul255(dp[k], t);
- dp[n1] = a + fz_mul255(dp[n1], t);
+ if(da)
+ dp[n1] = a + fz_mul255(dp[n1], t);
if (hp)
hp[0] = a + fz_mul255(hp[0], t);
}
}
}
- dp += n;
+ dp += n1+da;
if (hp)
hp++;
u += fa;
@@ -456,15 +463,15 @@ fz_paint_affine_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa,
int vi = v >> 16;
if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
{
- byte *sample = sp + ((vi * sw + ui) * n);
- int a = sample[n1];
+ byte *sample = sp + (vi * ss) + (ui * (n1+sa));
+ int a = sa ? sample[n1] : 255;
/* If a is 0, then sample[k] = 0 for all k, as premultiplied */
if (a != 0)
{
int t = 255 - a;
if (t == 0)
{
- if (n == 4)
+ if (n1+da == 4)
{
*(int *)dp = *(int *)sample;
}
@@ -472,7 +479,8 @@ fz_paint_affine_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa,
{
for (k = 0; k < n1; k++)
dp[k] = sample[k];
- dp[n1] = a;
+ if (da)
+ dp[n1] = a;
}
if (hp)
hp[0] = a;
@@ -481,13 +489,14 @@ fz_paint_affine_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa,
{
for (k = 0; k < n1; k++)
dp[k] = sample[k] + fz_mul255(dp[k], t);
- dp[n1] = a + fz_mul255(dp[n1], t);
+ if (da)
+ dp[n1] = a + fz_mul255(dp[n1], t);
if (hp)
hp[0] = a + fz_mul255(hp[0], t);
}
}
}
- dp += n;
+ dp += n1+da;
if (hp)
hp++;
u += fa;
@@ -497,22 +506,21 @@ fz_paint_affine_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa,
}
static inline void
-fz_paint_affine_solid_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, byte *hp)
+fz_paint_affine_solid_g2rgb_near(byte *dp, int da, byte *sp, int sw, int sh, int ss, int sa, int u, int v, int fa, int fb, int w, byte *hp)
{
if (fa == 0)
{
int ui = u >> 16;
if (ui < 0 || ui >= sw)
return;
- sp += ui * 2;
- sw *= 2;
+ sp += ui * (1+sa);
while (w--)
{
int vi = v >> 16;
if (vi >= 0 && vi < sh)
{
- byte *sample = sp + (vi * sw);
- int a = sample[1];
+ byte *sample = sp + (vi * ss);
+ int a = (sa ? sample[1] : 255);
if (a != 0)
{
int x = sample[0];
@@ -522,7 +530,8 @@ fz_paint_affine_solid_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int
dp[0] = x;
dp[1] = x;
dp[2] = x;
- dp[3] = a;
+ if (da)
+ dp[3] = a;
if (hp)
hp[0] = a;
}
@@ -531,13 +540,14 @@ fz_paint_affine_solid_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int
dp[0] = x + fz_mul255(dp[0], t);
dp[1] = x + fz_mul255(dp[1], t);
dp[2] = x + fz_mul255(dp[2], t);
- dp[3] = a + fz_mul255(dp[3], t);
+ if (da)
+ dp[3] = a + fz_mul255(dp[3], t);
if (hp)
hp[0] = a + fz_mul255(hp[0], t);
}
}
}
- dp += 4;
+ dp += 3 + da;
if (hp)
hp++;
v += fb;
@@ -548,14 +558,14 @@ fz_paint_affine_solid_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int
int vi = v >> 16;
if (vi < 0 || vi >= sh)
return;
- sp += vi * sw * 2;
+ sp += vi * ss;
while (w--)
{
int ui = u >> 16;
if (ui >= 0 && ui < sw)
{
- byte *sample = sp + (ui * 2);
- int a = sample[1];
+ byte *sample = sp + (ui * (1+sa));
+ int a = (sa ? sample[1] : 255);
if (a != 0)
{
int x = sample[0];
@@ -565,7 +575,8 @@ fz_paint_affine_solid_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int
dp[0] = x;
dp[1] = x;
dp[2] = x;
- dp[3] = a;
+ if (da)
+ dp[3] = a;
if (hp)
hp[0] = a;
}
@@ -574,13 +585,14 @@ fz_paint_affine_solid_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int
dp[0] = x + fz_mul255(dp[0], t);
dp[1] = x + fz_mul255(dp[1], t);
dp[2] = x + fz_mul255(dp[2], t);
- dp[3] = a + fz_mul255(dp[3], t);
+ if (da)
+ dp[3] = a + fz_mul255(dp[3], t);
if (hp)
hp[0] = a + fz_mul255(hp[0], t);
}
}
}
- dp += 4;
+ dp += 3 + da;
if (hp)
hp++;
u += fa;
@@ -594,8 +606,8 @@ fz_paint_affine_solid_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int
int vi = v >> 16;
if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
{
- byte *sample = sp + ((vi * sw + ui) * 2);
- int a = sample[1];
+ byte *sample = sp + (vi * ss) + (ui * (1+sa));
+ int a = sa ? sample[1] : 255;
if (a != 0)
{
int x = sample[0];
@@ -605,7 +617,8 @@ fz_paint_affine_solid_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int
dp[0] = x;
dp[1] = x;
dp[2] = x;
- dp[3] = a;
+ if (da)
+ dp[3] = a;
if (hp)
hp[0] = a;
}
@@ -614,13 +627,14 @@ fz_paint_affine_solid_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int
dp[0] = x + fz_mul255(dp[0], t);
dp[1] = x + fz_mul255(dp[1], t);
dp[2] = x + fz_mul255(dp[2], t);
- dp[3] = a + fz_mul255(dp[3], t);
+ if (da)
+ dp[3] = a + fz_mul255(dp[3], t);
if (hp)
hp[0] = a + fz_mul255(hp[0], t);
}
}
}
- dp += 4;
+ dp += 3 + da;
if (hp)
hp++;
u += fa;
@@ -632,9 +646,8 @@ fz_paint_affine_solid_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int
/* Blend non-premultiplied color in source image mask over destination */
static inline void
-fz_paint_affine_color_N_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, byte *color, byte *hp)
+fz_paint_affine_color_N_lerp(byte *dp, int da, byte *sp, int sw, int sh, int ss, int u, int v, int fa, int fb, int w, int n1, byte *color, byte *hp)
{
- int n1 = n - 1;
int sa = color[n1];
int k;
@@ -646,19 +659,20 @@ fz_paint_affine_color_N_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, i
int vi = v >> 16;
int uf = u & 0xffff;
int vf = v & 0xffff;
- byte *a = sample_nearest(sp, sw, sh, 1, ui, vi);
- byte *b = sample_nearest(sp, sw, sh, 1, ui+1, vi);
- byte *c = sample_nearest(sp, sw, sh, 1, ui, vi+1);
- byte *d = sample_nearest(sp, sw, sh, 1, ui+1, vi+1);
+ byte *a = sample_nearest(sp, sw, sh, ss, 1, ui, vi);
+ byte *b = sample_nearest(sp, sw, sh, ss, 1, ui+1, vi);
+ byte *c = sample_nearest(sp, sw, sh, ss, 1, ui, vi+1);
+ byte *d = sample_nearest(sp, sw, sh, ss, 1, ui+1, vi+1);
int ma = bilerp(a[0], b[0], c[0], d[0], uf, vf);
int masa = FZ_COMBINE(FZ_EXPAND(ma), sa);
for (k = 0; k < n1; k++)
dp[k] = FZ_BLEND(color[k], dp[k], masa);
- dp[n1] = FZ_BLEND(255, dp[n1], masa);
+ if (da)
+ dp[n1] = FZ_BLEND(255, dp[n1], masa);
if (hp)
hp[0] = FZ_BLEND(255, hp[0], masa);
}
- dp += n;
+ dp += n1 + da;
if (hp)
hp++;
u += fa;
@@ -667,9 +681,8 @@ fz_paint_affine_color_N_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, i
}
static inline void
-fz_paint_affine_color_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, byte *color, byte *hp)
+fz_paint_affine_color_N_near(byte *dp, int da, byte *sp, int sw, int sh, int ss, int u, int v, int fa, int fb, int w, int n1, byte *color, byte *hp)
{
- int n1 = n-1;
int sa = color[n1];
int k;
@@ -679,15 +692,16 @@ fz_paint_affine_color_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, i
int vi = v >> 16;
if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
{
- int ma = sp[vi * sw + ui];
+ int ma = sp[vi * ss + ui];
int masa = FZ_COMBINE(FZ_EXPAND(ma), sa);
for (k = 0; k < n1; k++)
dp[k] = FZ_BLEND(color[k], dp[k], masa);
- dp[n1] = FZ_BLEND(255, dp[n1], masa);
+ if (da)
+ dp[n1] = FZ_BLEND(255, dp[n1], masa);
if (hp)
hp[0] = FZ_BLEND(255, hp[0], masa);
}
- dp += n;
+ dp += n1+da;
if (hp)
hp++;
u += fa;
@@ -696,104 +710,372 @@ fz_paint_affine_color_N_near(byte *dp, byte *sp, int sw, int sh, int u, int v, i
}
static void
-fz_paint_affine_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color/*unused*/, byte *hp)
+fz_paint_affine_lerp(byte *dp, int da, byte *sp, int sw, int sh, int ss, int sa, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color/*unused*/, byte *hp)
{
- if (alpha == 255)
+ if (da)
{
- switch (n)
+ if (sa)
{
- case 1: fz_paint_affine_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, 1, hp); break;
- case 2: fz_paint_affine_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, 2, hp); break;
- case 4: fz_paint_affine_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, 4, hp); break;
- default: fz_paint_affine_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, n, hp); break;
+ if (alpha == 255)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_affine_N_lerp(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, 1, hp); break;
+ case 3: fz_paint_affine_N_lerp(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, 3, hp); break;
+ case 4: fz_paint_affine_N_lerp(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, 4, hp); break;
+ default: fz_paint_affine_N_lerp(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, n, hp); break;
+ }
+ }
+ else if (alpha > 0)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_affine_alpha_N_lerp(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, 1, alpha, hp); break;
+ case 3: fz_paint_affine_alpha_N_lerp(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, 3, alpha, hp); break;
+ case 4: fz_paint_affine_alpha_N_lerp(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, 4, alpha, hp); break;
+ default: fz_paint_affine_alpha_N_lerp(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, n, alpha, hp); break;
+ }
+ }
+ }
+ else
+ {
+ if (alpha == 255)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_affine_N_lerp(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, 1, hp); break;
+ case 3: fz_paint_affine_N_lerp(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, 3, hp); break;
+ case 4: fz_paint_affine_N_lerp(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, 4, hp); break;
+ default: fz_paint_affine_N_lerp(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, n, hp); break;
+ }
+ }
+ else if (alpha > 0)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_affine_alpha_N_lerp(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, 1, alpha, hp); break;
+ case 3: fz_paint_affine_alpha_N_lerp(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, 3, alpha, hp); break;
+ case 4: fz_paint_affine_alpha_N_lerp(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, 4, alpha, hp); break;
+ default: fz_paint_affine_alpha_N_lerp(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, n, alpha, hp); break;
+ }
+ }
}
}
- else if (alpha > 0)
+ else
{
- switch (n)
+ if (sa)
{
- case 1: fz_paint_affine_alpha_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, 1, alpha, hp); break;
- case 2: fz_paint_affine_alpha_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, 2, alpha, hp); break;
- case 4: fz_paint_affine_alpha_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, 4, alpha, hp); break;
- default: fz_paint_affine_alpha_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, n, alpha, hp); break;
+ if (alpha == 255)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_affine_N_lerp(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, 1, hp); break;
+ case 3: fz_paint_affine_N_lerp(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, 3, hp); break;
+ case 4: fz_paint_affine_N_lerp(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, 4, hp); break;
+ default: fz_paint_affine_N_lerp(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, n, hp); break;
+ }
+ }
+ else if (alpha > 0)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_affine_alpha_N_lerp(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, 1, alpha, hp); break;
+ case 3: fz_paint_affine_alpha_N_lerp(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, 3, alpha, hp); break;
+ case 4: fz_paint_affine_alpha_N_lerp(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, 4, alpha, hp); break;
+ default: fz_paint_affine_alpha_N_lerp(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, n, alpha, hp); break;
+ }
+ }
+ }
+ else
+ {
+ if (alpha == 255)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_affine_N_lerp(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, 1, hp); break;
+ case 3: fz_paint_affine_N_lerp(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, 3, hp); break;
+ case 4: fz_paint_affine_N_lerp(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, 4, hp); break;
+ default: fz_paint_affine_N_lerp(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, n, hp); break;
+ }
+ }
+ else if (alpha > 0)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_affine_alpha_N_lerp(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, 1, alpha, hp); break;
+ case 3: fz_paint_affine_alpha_N_lerp(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, 3, alpha, hp); break;
+ case 4: fz_paint_affine_alpha_N_lerp(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, 4, alpha, hp); break;
+ default: fz_paint_affine_alpha_N_lerp(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, n, alpha, hp); break;
+ }
+ }
}
}
}
static void
-fz_paint_affine_g2rgb_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color/*unused*/, byte *hp)
+fz_paint_affine_g2rgb_lerp(byte *dp, int da, byte *sp, int sw, int sh, int ss, int sa, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color/*unused*/, byte *hp)
{
- if (alpha == 255)
+ if (da)
{
- fz_paint_affine_solid_g2rgb_lerp(dp, sp, sw, sh, u, v, fa, fb, w, hp);
+ if (sa)
+ {
+ if (alpha == 255)
+ {
+ fz_paint_affine_solid_g2rgb_lerp(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, hp);
+ }
+ else if (alpha > 0)
+ {
+ fz_paint_affine_alpha_g2rgb_lerp(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, alpha, hp);
+ }
+ }
+ else
+ {
+ if (alpha == 255)
+ {
+ fz_paint_affine_solid_g2rgb_lerp(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, hp);
+ }
+ else if (alpha > 0)
+ {
+ fz_paint_affine_alpha_g2rgb_lerp(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, alpha, hp);
+ }
+ }
}
- else if (alpha > 0)
+ else
{
- fz_paint_affine_alpha_g2rgb_lerp(dp, sp, sw, sh, u, v, fa, fb, w, alpha, hp);
+ if (sa)
+ {
+ if (alpha == 255)
+ {
+ fz_paint_affine_solid_g2rgb_lerp(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, hp);
+ }
+ else if (alpha > 0)
+ {
+ fz_paint_affine_alpha_g2rgb_lerp(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, alpha, hp);
+ }
+ }
+ else
+ {
+ if (alpha == 255)
+ {
+ fz_paint_affine_solid_g2rgb_lerp(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, hp);
+ }
+ else if (alpha > 0)
+ {
+ fz_paint_affine_alpha_g2rgb_lerp(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, alpha, hp);
+ }
+ }
}
}
static void
-fz_paint_affine_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color/*unused */, byte *hp)
+fz_paint_affine_near(byte *dp, int da, byte *sp, int sw, int sh, int ss, int sa, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color/*unused */, byte *hp)
{
- if (alpha == 255)
+ if (da)
{
- switch (n)
+ if (sa)
+ {
+ if (alpha == 255)
+ {
+ switch (n)
+ {
+ case 0: fz_paint_affine_N_near(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, 0, hp); break;
+ case 1: fz_paint_affine_N_near(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, 1, hp); break;
+ case 3: fz_paint_affine_N_near(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, 3, hp); break;
+ case 4: fz_paint_affine_N_near(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, 4, hp); break;
+ default: fz_paint_affine_N_near(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, n, hp); break;
+ }
+ }
+ else if (alpha > 0)
+ {
+ switch (n)
+ {
+ case 0: fz_paint_affine_alpha_N_near(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, 0, alpha, hp); break;
+ case 1: fz_paint_affine_alpha_N_near(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, 1, alpha, hp); break;
+ case 3: fz_paint_affine_alpha_N_near(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, 3, alpha, hp); break;
+ case 4: fz_paint_affine_alpha_N_near(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, 4, alpha, hp); break;
+ default: fz_paint_affine_alpha_N_near(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, n, alpha, hp); break;
+ }
+ }
+ }
+ else
{
- case 1: fz_paint_affine_N_near(dp, sp, sw, sh, u, v, fa, fb, w, 1, hp); break;
- case 2: fz_paint_affine_N_near(dp, sp, sw, sh, u, v, fa, fb, w, 2, hp); break;
- case 4: fz_paint_affine_N_near(dp, sp, sw, sh, u, v, fa, fb, w, 4, hp); break;
- case 5: fz_paint_affine_N_near(dp, sp, sw, sh, u, v, fa, fb, w, 5, hp); break;
- default: fz_paint_affine_N_near(dp, sp, sw, sh, u, v, fa, fb, w, n, hp); break;
+ if (alpha == 255)
+ {
+ switch (n)
+ {
+ case 0: fz_paint_affine_N_near(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, 0, hp); break;
+ case 1: fz_paint_affine_N_near(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, 1, hp); break;
+ case 3: fz_paint_affine_N_near(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, 3, hp); break;
+ case 4: fz_paint_affine_N_near(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, 4, hp); break;
+ default: fz_paint_affine_N_near(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, n, hp); break;
+ }
+ }
+ else if (alpha > 0)
+ {
+ switch (n)
+ {
+ case 0: fz_paint_affine_alpha_N_near(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, 0, alpha, hp); break;
+ case 1: fz_paint_affine_alpha_N_near(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, 1, alpha, hp); break;
+ case 3: fz_paint_affine_alpha_N_near(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, 3, alpha, hp); break;
+ case 4: fz_paint_affine_alpha_N_near(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, 4, alpha, hp); break;
+ default: fz_paint_affine_alpha_N_near(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, n, alpha, hp); break;
+ }
+ }
}
}
- else if (alpha > 0)
+ else
{
- switch (n)
+ if (sa)
{
- case 1: fz_paint_affine_alpha_N_near(dp, sp, sw, sh, u, v, fa, fb, w, 1, alpha, hp); break;
- case 2: fz_paint_affine_alpha_N_near(dp, sp, sw, sh, u, v, fa, fb, w, 2, alpha, hp); break;
- case 4: fz_paint_affine_alpha_N_near(dp, sp, sw, sh, u, v, fa, fb, w, 4, alpha, hp); break;
- case 5: fz_paint_affine_alpha_N_near(dp, sp, sw, sh, u, v, fa, fb, w, 5, alpha, hp); break;
- default: fz_paint_affine_alpha_N_near(dp, sp, sw, sh, u, v, fa, fb, w, n, alpha, hp); break;
+ if (alpha == 255)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_affine_N_near(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, 1, hp); break;
+ case 3: fz_paint_affine_N_near(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, 3, hp); break;
+ case 4: fz_paint_affine_N_near(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, 4, hp); break;
+ default: fz_paint_affine_N_near(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, n, hp); break;
+ }
+ }
+ else if (alpha > 0)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_affine_alpha_N_near(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, 1, alpha, hp); break;
+ case 3: fz_paint_affine_alpha_N_near(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, 3, alpha, hp); break;
+ case 4: fz_paint_affine_alpha_N_near(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, 4, alpha, hp); break;
+ default: fz_paint_affine_alpha_N_near(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, n, alpha, hp); break;
+ }
+ }
+ }
+ else
+ {
+ if (alpha == 255)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_affine_N_near(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, 1, hp); break;
+ case 3: fz_paint_affine_N_near(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, 3, hp); break;
+ case 4: fz_paint_affine_N_near(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, 4, hp); break;
+ default: fz_paint_affine_N_near(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, n, hp); break;
+ }
+ }
+ else if (alpha > 0)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_affine_alpha_N_near(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, 1, alpha, hp); break;
+ case 3: fz_paint_affine_alpha_N_near(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, 3, alpha, hp); break;
+ case 4: fz_paint_affine_alpha_N_near(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, 4, alpha, hp); break;
+ default: fz_paint_affine_alpha_N_near(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, n, alpha, hp); break;
+ }
+ }
}
}
}
static void
-fz_paint_affine_g2rgb_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color/*unused*/, byte *hp)
+fz_paint_affine_g2rgb_near(byte *dp, int da, byte *sp, int sw, int sh, int ss, int sa, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color/*unused*/, byte *hp)
{
- if (alpha == 255)
+ if (da)
{
- fz_paint_affine_solid_g2rgb_near(dp, sp, sw, sh, u, v, fa, fb, w, hp);
+ if (sa)
+ {
+ if (alpha == 255)
+ {
+ fz_paint_affine_solid_g2rgb_near(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, hp);
+ }
+ else if (alpha > 0)
+ {
+ fz_paint_affine_alpha_g2rgb_near(dp, 1, sp, sw, sh, ss, 1, u, v, fa, fb, w, alpha, hp);
+ }
+ }
+ else
+ {
+ if (alpha == 255)
+ {
+ fz_paint_affine_solid_g2rgb_near(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, hp);
+ }
+ else if (alpha > 0)
+ {
+ fz_paint_affine_alpha_g2rgb_near(dp, 1, sp, sw, sh, ss, 0, u, v, fa, fb, w, alpha, hp);
+ }
+ }
}
- else if (alpha > 0)
+ else
{
- fz_paint_affine_alpha_g2rgb_near(dp, sp, sw, sh, u, v, fa, fb, w, alpha, hp);
+ if (sa)
+ {
+ if (alpha == 255)
+ {
+ fz_paint_affine_solid_g2rgb_near(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, hp);
+ }
+ else if (alpha > 0)
+ {
+ fz_paint_affine_alpha_g2rgb_near(dp, 0, sp, sw, sh, ss, 1, u, v, fa, fb, w, alpha, hp);
+ }
+ }
+ else
+ {
+ if (alpha == 255)
+ {
+ fz_paint_affine_solid_g2rgb_near(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, hp);
+ }
+ else if (alpha > 0)
+ {
+ fz_paint_affine_alpha_g2rgb_near(dp, 0, sp, sw, sh, ss, 0, u, v, fa, fb, w, alpha, hp);
+ }
+ }
}
}
static void
-fz_paint_affine_color_lerp(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha/*unused*/, byte *color, byte *hp)
+fz_paint_affine_color_lerp(byte *dp, int da, byte *sp, int sw, int sh, int ss, int sa, int u, int v, int fa, int fb, int w, int n, int alpha/*unused*/, byte *color, byte *hp)
{
- switch (n)
+ if (da)
{
- case 2: fz_paint_affine_color_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, 2, color, hp); break;
- case 4: fz_paint_affine_color_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, 4, color, hp); break;
- case 5: fz_paint_affine_color_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, 5, color, hp); break;
- default: fz_paint_affine_color_N_lerp(dp, sp, sw, sh, u, v, fa, fb, w, n, color, hp); break;
+ switch (n)
+ {
+ case 1: fz_paint_affine_color_N_lerp(dp, 1, sp, sw, sh, ss, u, v, fa, fb, w, 1, color, hp); break;
+ case 3: fz_paint_affine_color_N_lerp(dp, 1, sp, sw, sh, ss, u, v, fa, fb, w, 3, color, hp); break;
+ case 4: fz_paint_affine_color_N_lerp(dp, 1, sp, sw, sh, ss, u, v, fa, fb, w, 4, color, hp); break;
+ default: fz_paint_affine_color_N_lerp(dp, 1, sp, sw, sh, ss, u, v, fa, fb, w, n, color, hp); break;
+ }
+ }
+ else
+ {
+ switch (n)
+ {
+ case 1: fz_paint_affine_color_N_lerp(dp, 0, sp, sw, sh, ss, u, v, fa, fb, w, 1, color, hp); break;
+ case 3: fz_paint_affine_color_N_lerp(dp, 0, sp, sw, sh, ss, u, v, fa, fb, w, 3, color, hp); break;
+ case 4: fz_paint_affine_color_N_lerp(dp, 0, sp, sw, sh, ss, u, v, fa, fb, w, 4, color, hp); break;
+ default: fz_paint_affine_color_N_lerp(dp, 0, sp, sw, sh, ss, u, v, fa, fb, w, n, color, hp); break;
+ }
}
}
static void
-fz_paint_affine_color_near(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha/*unused*/, byte *color, byte *hp)
+fz_paint_affine_color_near(byte *dp, int da, byte *sp, int sw, int sh, int ss, int sa, int u, int v, int fa, int fb, int w, int n, int alpha/*unused*/, byte *color, byte *hp)
{
- switch (n)
+ if (da)
{
- case 2: fz_paint_affine_color_N_near(dp, sp, sw, sh, u, v, fa, fb, w, 2, color, hp); break;
- case 4: fz_paint_affine_color_N_near(dp, sp, sw, sh, u, v, fa, fb, w, 4, color, hp); break;
- case 5: fz_paint_affine_color_N_near(dp, sp, sw, sh, u, v, fa, fb, w, 5, color, hp); break;
- default: fz_paint_affine_color_N_near(dp, sp, sw, sh, u, v, fa, fb, w, n, color, hp); break;
+ switch (n)
+ {
+ case 1: fz_paint_affine_color_N_near(dp, 1, sp, sw, sh, ss, u, v, fa, fb, w, 1, color, hp); break;
+ case 3: fz_paint_affine_color_N_near(dp, 1, sp, sw, sh, ss, u, v, fa, fb, w, 3, color, hp); break;
+ case 4: fz_paint_affine_color_N_near(dp, 1, sp, sw, sh, ss, u, v, fa, fb, w, 4, color, hp); break;
+ default: fz_paint_affine_color_N_near(dp, 1, sp, sw, sh, ss, u, v, fa, fb, w, n, color, hp); break;
+ }
+ }
+ else
+ {
+ switch (n)
+ {
+ case 1: fz_paint_affine_color_N_near(dp, 0, sp, sw, sh, ss, u, v, fa, fb, w, 1, color, hp); break;
+ case 3: fz_paint_affine_color_N_near(dp, 0, sp, sw, sh, ss, u, v, fa, fb, w, 3, color, hp); break;
+ case 4: fz_paint_affine_color_N_near(dp, 0, sp, sw, sh, ss, u, v, fa, fb, w, 4, color, hp); break;
+ default: fz_paint_affine_color_N_near(dp, 0, sp, sw, sh, ss, u, v, fa, fb, w, n, color, hp); break;
+ }
}
}
@@ -994,10 +1276,10 @@ fz_paint_image_imp(fz_pixmap *dst, const fz_irect *scissor, fz_pixmap *shape, fz
byte *dp, *sp, *hp;
int u, v, fa, fb, fc, fd;
int x, y, w, h;
- int sw, sh, n, hw;
+ int sw, sh, ss, sa, n, hs, da;
fz_irect bbox;
int dolerp;
- void (*paintfn)(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color, byte *hp);
+ void (*paintfn)(byte *dp, int da, byte *sp, int sw, int sh, int ss, int sa, int u, int v, int fa, int fb, int w, int n, int alpha, byte *color, byte *hp);
fz_matrix local_ctm = *ctm;
fz_rect rect;
int is_rectilinear;
@@ -1062,27 +1344,35 @@ fz_paint_image_imp(fz_pixmap *dst, const fz_irect *scissor, fz_pixmap *shape, fz
u = (int)((local_ctm.a * x) + (local_ctm.c * y) + local_ctm.e + ((local_ctm.a + local_ctm.c) * .5f));
v = (int)((local_ctm.b * x) + (local_ctm.d * y) + local_ctm.f + ((local_ctm.b + local_ctm.d) * .5f));
- dp = dst->samples + (unsigned int)(((y - dst->y) * dst->w + (x - dst->x)) * dst->n);
- n = dst->n;
+ dp = dst->samples + (unsigned int)((y - dst->y) * dst->stride + (x - dst->x) * dst->n);
+ da = dst->alpha;
+ n = dst->n - da;
sp = img->samples;
sw = img->w;
sh = img->h;
+ ss = img->stride;
+ sa = img->alpha;
if (shape)
{
- hw = shape->w;
- hp = shape->samples + (unsigned int)(((y - shape->y) * hw) + x - shape->x);
+ hs = shape->stride;
+ hp = shape->samples + (unsigned int)((y - shape->y) * shape->stride + x - shape->x);
}
else
{
- hw = 0;
+ hs = 0;
hp = NULL;
}
/* TODO: if (fb == 0 && fa == 1) call fz_paint_span */
- if (dst->n == 4 && img->n == 2)
+ /* Sometimes we can get an alpha only input to be
+ * ploted. In this case treat it as a greyscale
+ * input. */
+ if (img->n == sa && n > 0)
+ sa = 0;
+
+ if (n == 3 && img->n == 1 + sa && !color)
{
- assert(!color);
if (dolerp)
paintfn = fz_paint_affine_g2rgb_lerp;
else
@@ -1090,6 +1380,7 @@ fz_paint_image_imp(fz_pixmap *dst, const fz_irect *scissor, fz_pixmap *shape, fz
}
else
{
+ assert((!color && img->n - sa == n) || (color && img->n - sa == 1));
if (dolerp)
{
if (color)
@@ -1116,9 +1407,9 @@ fz_paint_image_imp(fz_pixmap *dst, const fz_irect *scissor, fz_pixmap *shape, fz
while (h--)
{
- paintfn(dp, sp, sw, sh, u, v, fa, fb, w, n, alpha, color, hp);
- dp += dst->w * n;
- hp += hw;
+ paintfn(dp, da, sp, sw, sh, ss, sa, u, v, fa, fb, w, n, alpha, color, hp);
+ dp += dst->stride;
+ hp += hs;
u += fc;
v += fd;
}
@@ -1134,6 +1425,6 @@ fz_paint_image_with_color(fz_pixmap *dst, const fz_irect *scissor, fz_pixmap *sh
void
fz_paint_image(fz_pixmap *dst, const fz_irect *scissor, fz_pixmap *shape, fz_pixmap *img, const fz_matrix *ctm, int alpha, int lerp_allowed, int as_tiled)
{
- assert(dst->n == img->n || (dst->n == 4 && img->n == 2));
+ assert(dst->n - dst->alpha == img->n - img->alpha|| (dst->n == 3 + dst->alpha && img->n == 1 + img->alpha));
fz_paint_image_imp(dst, scissor, shape, img, ctm, NULL, alpha, lerp_allowed, as_tiled);
}
diff --git a/source/fitz/draw-blend.c b/source/fitz/draw-blend.c
index 57aa28b1..31914ae1 100644
--- a/source/fitz/draw-blend.c
+++ b/source/fitz/draw-blend.c
@@ -268,15 +268,14 @@ fz_blend_pixel(unsigned char dp[3], unsigned char bp[3], unsigned char sp[3], in
/* Blending loops */
-void
-fz_blend_separable(byte * restrict bp, byte * restrict sp, int n, int w, int blendmode)
+static inline void
+fz_blend_separable(byte * restrict bp, int bal, byte * restrict sp, int sal, int n1, int w, int blendmode)
{
int k;
- int n1 = n - 1;
while (w--)
{
- int sa = sp[n1];
- int ba = bp[n1];
+ int sa = (sal ? sp[n1] : 255);
+ int ba = (bal ? bp[n1] : 255);
int saba = fz_mul255(sa, ba);
/* ugh, division to get non-premul components */
@@ -309,22 +308,23 @@ fz_blend_separable(byte * restrict bp, byte * restrict sp, int n, int w, int ble
bp[k] = fz_mul255(255 - sa, bp[k]) + fz_mul255(255 - ba, sp[k]) + fz_mul255(saba, rc);
}
- bp[k] = ba + sa - saba;
+ if (bal)
+ bp[k] = ba + sa - saba;
- sp += n;
- bp += n;
+ sp += n1 + sal;
+ bp += n1 + bal;
}
}
-void
-fz_blend_nonseparable(byte * restrict bp, byte * restrict sp, int w, int blendmode)
+static void
+fz_blend_nonseparable(byte * restrict bp, int bal, byte * restrict sp, int sal, int w, int blendmode)
{
while (w--)
{
unsigned char rr, rg, rb;
- int sa = sp[3];
- int ba = bp[3];
+ int sa = (sal ? sp[3] : 255);
+ int ba = (bal ? bp[3] : 255);
int saba = fz_mul255(sa, ba);
/* ugh, division to get non-premul components */
@@ -359,18 +359,18 @@ fz_blend_nonseparable(byte * restrict bp, byte * restrict sp, int w, int blendmo
bp[0] = fz_mul255(255 - sa, bp[0]) + fz_mul255(255 - ba, sp[0]) + fz_mul255(saba, rr);
bp[1] = fz_mul255(255 - sa, bp[1]) + fz_mul255(255 - ba, sp[1]) + fz_mul255(saba, rg);
bp[2] = fz_mul255(255 - sa, bp[2]) + fz_mul255(255 - ba, sp[2]) + fz_mul255(saba, rb);
- bp[3] = ba + sa - saba;
+ if (bal)
+ bp[3] = ba + sa - saba;
- sp += 4;
- bp += 4;
+ sp += 3 + sal;
+ bp += 3 + bal;
}
}
-static void
-fz_blend_separable_nonisolated(byte * restrict bp, byte * restrict sp, int n, int w, int blendmode, byte * restrict hp, int alpha)
+static inline void
+fz_blend_separable_nonisolated(byte * restrict bp, int bal, byte * restrict sp, int sal, int n1, int w, int blendmode, byte * restrict hp, int alpha)
{
int k;
- int n1 = n - 1;
if (alpha == 255 && blendmode == 0)
{
@@ -384,14 +384,16 @@ fz_blend_separable_nonisolated(byte * restrict bp, byte * restrict sp, int n, in
/* If ha == 0 then leave everything unchanged */
if (ha != 0)
{
- for (k = 0; k < n; k++)
+ for (k = 0; k < n1; k++)
{
bp[k] = sp[k];
}
+ if (bal)
+ bp[k] = (sal ? sp[k] : 255);
}
- sp += n;
- bp += n;
+ sp += n1 + sal;
+ bp += n1 + bal;
}
return;
}
@@ -403,11 +405,11 @@ fz_blend_separable_nonisolated(byte * restrict bp, byte * restrict sp, int n, in
while (haa != 0) /* Use while, so we can break out */
{
int sa, ba, bahaa, ra, invsa, invba, invha, invra;
- sa = sp[n1];
+ sa = (sal ? sp[n1] : 255);
if (sa == 0)
break; /* No change! */
invsa = sa ? 255 * 256 / sa : 0;
- ba = bp[n1];
+ ba = (bal ? bp[n1] : 255);
if (ba == 0)
{
/* Just copy pixels (allowing for change in
@@ -416,7 +418,8 @@ fz_blend_separable_nonisolated(byte * restrict bp, byte * restrict sp, int n, in
{
bp[k] = fz_mul255((sp[k] * invsa) >> 8, haa);
}
- bp[n1] = haa;
+ if (bal)
+ bp[n1] = haa;
break;
}
bahaa = fz_mul255(ba, haa);
@@ -426,7 +429,9 @@ fz_blend_separable_nonisolated(byte * restrict bp, byte * restrict sp, int n, in
/* Calculate result_alpha - a combination of the
* background alpha, and 'shape' */
- ra = bp[n1] = ba - bahaa + haa;
+ ra = ba - bahaa + haa;
+ if (bal)
+ bp[n1] = ra;
if (ra == 0)
break;
/* Because we are a non-isolated group, we need to
@@ -483,18 +488,18 @@ fz_blend_separable_nonisolated(byte * restrict bp, byte * restrict sp, int n, in
rc = bc + fz_mul255(sa, fz_mul255(255 - ba, sc) + fz_mul255(ba, rc) - bc);
if (rc < 0) rc = 0;
if (rc > 255) rc = 255;
- bp[k] = fz_mul255(rc, ra);
+ bp[k] = fz_mul255(rc, ra);
}
break;
}
- sp += n;
- bp += n;
+ sp += n1 + sal;
+ bp += n1 + bal;
}
}
-static void
-fz_blend_nonseparable_nonisolated(byte * restrict bp, byte * restrict sp, int w, int blendmode, byte * restrict hp, int alpha)
+static inline void
+fz_blend_nonseparable_nonisolated(byte * restrict bp, int bal, byte * restrict sp, int sal, int w, int blendmode, byte * restrict hp, int alpha)
{
while (w--)
{
@@ -502,12 +507,14 @@ fz_blend_nonseparable_nonisolated(byte * restrict bp, byte * restrict sp, int w,
int haa = fz_mul255(ha, alpha);
if (haa != 0)
{
- int sa = sp[3];
- int ba = bp[3];
+ int sa = (sal ? sp[3] : 255);
+ int ba = (bal ? bp[3] : 255);
int baha = fz_mul255(ba, haa);
/* Calculate result_alpha */
- int ra = bp[3] = ba - baha + haa;
+ int ra = ba - baha + haa;
+ if (bal)
+ bp[3] = ra;
if (ra != 0)
{
/* Because we are a non-isolated group, we
@@ -566,8 +573,8 @@ fz_blend_nonseparable_nonisolated(byte * restrict bp, byte * restrict sp, int w,
}
}
- sp += 4;
- bp += 4;
+ sp += 3 + sal;
+ bp += 3 + bal;
}
}
@@ -578,16 +585,24 @@ fz_blend_pixmap(fz_pixmap *dst, fz_pixmap *src, int alpha, int blendmode, int is
fz_irect bbox;
fz_irect bbox2;
int x, y, w, h, n;
+ int da, sa;
/* TODO: fix this hack! */
if (isolated && alpha < 255)
{
+ int nn;
+ h = src->h;
sp = src->samples;
- n = src->w * src->h * src->n;
- while (n--)
+ nn = src->w * src->n;
+ while (h--)
{
- *sp = fz_mul255(*sp, alpha);
- sp++;
+ n = nn;
+ while (n--)
+ {
+ *sp = fz_mul255(*sp, alpha);
+ sp++;
+ }
+ sp += src->stride - nn;
}
}
@@ -601,36 +616,75 @@ fz_blend_pixmap(fz_pixmap *dst, fz_pixmap *src, int alpha, int blendmode, int is
h = bbox.y1 - bbox.y0;
n = src->n;
- sp = src->samples + (unsigned int)(((y - src->y) * src->w + (x - src->x)) * n);
- dp = dst->samples + (unsigned int)(((y - dst->y) * dst->w + (x - dst->x)) * n);
+ sp = src->samples + (unsigned int)((y - src->y) * src->stride + (x - src->x) * src->n);
+ sa = src->alpha;
+ dp = dst->samples + (unsigned int)((y - dst->y) * dst->stride + (x - dst->x) * dst->n);
+ da = dst->alpha;
- assert(src->n == dst->n);
+ n -= sa;
+ assert(n == dst->n - da);
if (!isolated)
{
- unsigned char *hp = shape->samples + (unsigned int)((y - shape->y) * shape->w + (x - shape->x));
+ unsigned char *hp = shape->samples + (unsigned int)((y - shape->y) * shape->stride + (x - shape->x));
while (h--)
{
- if (n == 4 && blendmode >= FZ_BLEND_HUE)
- fz_blend_nonseparable_nonisolated(dp, sp, w, blendmode, hp, alpha);
+ if (n == 3 && blendmode >= FZ_BLEND_HUE)
+ if (da)
+ if (sa)
+ fz_blend_nonseparable_nonisolated(dp, 1, sp, 1, w, blendmode, hp, alpha);
+ else
+ fz_blend_nonseparable_nonisolated(dp, 1, sp, 0, w, blendmode, hp, alpha);
+ else
+ if (sa)
+ fz_blend_nonseparable_nonisolated(dp, 0, sp, 1, w, blendmode, hp, alpha);
+ else
+ fz_blend_nonseparable_nonisolated(dp, 0, sp, 0, w, blendmode, hp, alpha);
else
- fz_blend_separable_nonisolated(dp, sp, n, w, blendmode, hp, alpha);
- sp += src->w * n;
- dp += dst->w * n;
- hp += shape->w;
+ if (da)
+ if (sa)
+ fz_blend_separable_nonisolated(dp, 1, sp, 1, n, w, blendmode, hp, alpha);
+ else
+ fz_blend_separable_nonisolated(dp, 1, sp, 0, n, w, blendmode, hp, alpha);
+ else
+ if (sa)
+ fz_blend_separable_nonisolated(dp, 0, sp, 1, n, w, blendmode, hp, alpha);
+ else
+ fz_blend_separable_nonisolated(dp, 0, sp, 0, n, w, blendmode, hp, alpha);
+ sp += src->stride;
+ dp += dst->stride;
+ hp += shape->stride;
}
}
else
{
while (h--)
{
- if (n == 4 && blendmode >= FZ_BLEND_HUE)
- fz_blend_nonseparable(dp, sp, w, blendmode);
+ if (n == 3 && blendmode >= FZ_BLEND_HUE)
+ if (da)
+ if (sa)
+ fz_blend_nonseparable(dp, 1, sp, 1, w, blendmode);
+ else
+ fz_blend_nonseparable(dp, 1, sp, 0, w, blendmode);
+ else
+ if (sa)
+ fz_blend_nonseparable(dp, 0, sp, 1, w, blendmode);
+ else
+ fz_blend_nonseparable(dp, 0, sp, 0, w, blendmode);
else
- fz_blend_separable(dp, sp, n, w, blendmode);
- sp += src->w * n;
- dp += dst->w * n;
+ if (da)
+ if (sa)
+ fz_blend_separable(dp, 1, sp, 1, n, w, blendmode);
+ else
+ fz_blend_separable(dp, 1, sp, 0, n, w, blendmode);
+ else
+ if (sa)
+ fz_blend_separable(dp, 0, sp, 1, n, w, blendmode);
+ else
+ fz_blend_separable(dp, 0, sp, 0, n, w, blendmode);
+ sp += src->stride;
+ dp += dst->stride;
}
}
}
diff --git a/source/fitz/draw-device.c b/source/fitz/draw-device.c
index 5b512c44..516e05bc 100644
--- a/source/fitz/draw-device.c
+++ b/source/fitz/draw-device.c
@@ -162,7 +162,7 @@ fz_knockout_begin(fz_context *ctx, fz_draw_device *dev)
fz_pixmap_bbox(ctx, state->dest, &bbox);
fz_intersect_irect(&bbox, &state->scissor);
- dest = fz_new_pixmap_with_bbox(ctx, state->dest->colorspace, &bbox);
+ dest = fz_new_pixmap_with_bbox(ctx, state->dest->colorspace, &bbox, state->dest->alpha || isolated);
if (isolated)
{
@@ -193,7 +193,7 @@ fz_knockout_begin(fz_context *ctx, fz_draw_device *dev)
}
else
{
- shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, shape);
}
#ifdef DUMP_GROUP_BLENDS
@@ -276,13 +276,10 @@ fz_draw_fill_path(fz_context *ctx, fz_device *devp, const fz_path *path, int eve
unsigned char colorbv[FZ_MAX_COLORS + 1];
float colorfv[FZ_MAX_COLORS];
fz_irect bbox;
- int i;
+ int i, n;
fz_draw_state *state = &dev->stack[dev->top];
fz_colorspace *model = state->dest->colorspace;
- if (model == NULL)
- model = fz_device_gray(ctx);
-
if (flatness < 0.001f)
flatness = 0.001f;
@@ -298,8 +295,9 @@ fz_draw_fill_path(fz_context *ctx, fz_device *devp, const fz_path *path, int eve
if (state->blendmode & FZ_BLEND_KNOCKOUT)
state = fz_knockout_begin(ctx, dev);
+ n = model ? model->n : 0;
fz_convert_color(ctx, model, colorfv, colorspace, color);
- for (i = 0; i < model->n; i++)
+ for (i = 0; i < n; i++)
colorbv[i] = colorfv[i] * 255;
colorbv[i] = alpha * 255;
@@ -331,14 +329,11 @@ fz_draw_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path, const
unsigned char colorbv[FZ_MAX_COLORS + 1];
float colorfv[FZ_MAX_COLORS];
fz_irect bbox;
- int i;
+ int i, n;
float aa_level = 2.0f/(fz_graphics_aa_level(ctx)+2);
fz_draw_state *state = &dev->stack[dev->top];
fz_colorspace *model = state->dest->colorspace;
- if (model == NULL)
- model = fz_device_gray(ctx);
-
if (linewidth * expansion < aa_level)
linewidth = aa_level / expansion;
if (flatness < 0.001f)
@@ -359,11 +354,19 @@ fz_draw_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path, const
if (state->blendmode & FZ_BLEND_KNOCKOUT)
state = fz_knockout_begin(ctx, dev);
+ n = model ? model->n : 0;
fz_convert_color(ctx, model, colorfv, colorspace, color);
- for (i = 0; i < model->n; i++)
+ for (i = 0; i < n; i++)
colorbv[i] = colorfv[i] * 255;
colorbv[i] = alpha * 255;
+#ifdef DUMP_GROUP_BLENDS
+ dump_spaces(dev->top, "");
+ fz_dump_blend(ctx, state->dest, "Before stroke ");
+ if (state->shape)
+ fz_dump_blend(ctx, state->shape, "/");
+ printf("\n");
+#endif
fz_scan_convert(ctx, gel, 0, &bbox, state->dest, colorbv);
if (state->shape)
{
@@ -377,6 +380,13 @@ fz_draw_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path, const
colorbv[0] = 255;
fz_scan_convert(ctx, gel, 0, &bbox, state->shape, colorbv);
}
+#ifdef DUMP_GROUP_BLENDS
+ dump_spaces(dev->top, "");
+ fz_dump_blend(ctx, state->dest, "After stroke ");
+ if (state->shape)
+ fz_dump_blend(ctx, state->shape, "/");
+ printf("\n");
+#endif
if (state->blendmode & FZ_BLEND_KNOCKOUT)
fz_knockout_end(ctx, dev);
@@ -424,13 +434,20 @@ fz_draw_clip_path(fz_context *ctx, fz_device *devp, const fz_path *path, int eve
fz_try(ctx)
{
- state[1].mask = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].mask = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, state[1].mask);
- state[1].dest = fz_new_pixmap_with_bbox(ctx, model, &bbox);
- fz_clear_pixmap(ctx, state[1].dest);
+ /* When there is no alpha in the current destination (state[0].dest->alpha == 0)
+ * we have a choice. We can either create the new destination WITH alpha, or
+ * we can copy the old pixmap contents in. We opt for the latter here, but
+ * may want to revisit this decision in future. */
+ state[1].dest = fz_new_pixmap_with_bbox(ctx, model, &bbox, state[0].dest->alpha);
+ if (state[0].dest->alpha)
+ fz_clear_pixmap(ctx, state[1].dest);
+ else
+ fz_copy_pixmap_rect(ctx, state[1].dest, state[0].dest, &bbox);
if (state[1].shape)
{
- state[1].shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, state[1].shape);
}
@@ -487,13 +504,20 @@ fz_draw_clip_stroke_path(fz_context *ctx, fz_device *devp, const fz_path *path,
fz_try(ctx)
{
- state[1].mask = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].mask = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, state[1].mask);
- state[1].dest = fz_new_pixmap_with_bbox(ctx, model, &bbox);
- fz_clear_pixmap(ctx, state[1].dest);
+ /* When there is no alpha in the current destination (state[0].dest->alpha == 0)
+ * we have a choice. We can either create the new destination WITH alpha, or
+ * we can copy the old pixmap contents in. We opt for the latter here, but
+ * may want to revisit this decision in future. */
+ state[1].dest = fz_new_pixmap_with_bbox(ctx, model, &bbox, state[0].dest->alpha);
+ if (state[0].dest->alpha)
+ fz_clear_pixmap(ctx, state[1].dest);
+ else
+ fz_copy_pixmap_rect(ctx, state[1].dest, state[0].dest, &bbox);
if (state->shape)
{
- state[1].shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, state[1].shape);
}
@@ -537,24 +561,25 @@ draw_glyph(unsigned char *colorbv, fz_pixmap *dst, fz_glyph *glyph,
skip_x = x - glyph->x - xorig;
skip_y = y - glyph->y - yorig;
- dp = dst->samples + (unsigned int)(((y - dst->y) * dst->w + (x - dst->x)) * dst->n);
-
msk = glyph->pixmap;
+ dp = dst->samples + (unsigned int)((y - dst->y) * dst->stride + (x - dst->x) * dst->n);
if (msk == NULL)
{
fz_paint_glyph(colorbv, dst, dp, glyph, w, h, skip_x, skip_y);
}
else
{
- unsigned char *mp = msk->samples + skip_y * msk->w + skip_x;
+ unsigned char *mp = msk->samples + skip_y * msk->stride + skip_x;
+ int da = dst->alpha;
+
while (h--)
{
if (dst->colorspace)
- fz_paint_span_with_color(dp, mp, dst->n, w, colorbv);
+ fz_paint_span_with_color(dp, mp, dst->n, w, colorbv, da);
else
- fz_paint_span(dp, mp, 1, w, 255);
- dp += dst->w * dst->n;
- mp += msk->w;
+ fz_paint_span(dp, da, mp, 1, 0, w, 255);
+ dp += dst->stride;
+ mp += msk->stride;
}
}
}
@@ -570,13 +595,14 @@ fz_draw_fill_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
unsigned char shapebv;
float colorfv[FZ_MAX_COLORS];
fz_text_span *span;
- int i;
+ int i, n;
if (state->blendmode & FZ_BLEND_KNOCKOUT)
state = fz_knockout_begin(ctx, dev);
+ n = model ? model->n : 0;
fz_convert_color(ctx, model, colorfv, colorspace, color);
- for (i = 0; i < model->n; i++)
+ for (i = 0; i < n; i++)
colorbv[i] = colorfv[i] * 255;
colorbv[i] = alpha * 255;
shapebv = 255;
@@ -599,7 +625,7 @@ fz_draw_fill_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
tm.f = span->items[i].y;
fz_concat(&trm, &tm, ctm);
- glyph = fz_render_glyph(ctx, span->font, gid, &trm, model, &state->scissor);
+ glyph = fz_render_glyph(ctx, span->font, gid, &trm, model, &state->scissor, state->dest->alpha);
if (glyph)
{
fz_pixmap *pixmap = glyph->pixmap;
@@ -651,13 +677,14 @@ fz_draw_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text, const
unsigned char colorbv[FZ_MAX_COLORS + 1];
float colorfv[FZ_MAX_COLORS];
fz_text_span *span;
- int i;
+ int i, n;
if (state->blendmode & FZ_BLEND_KNOCKOUT)
state = fz_knockout_begin(ctx, dev);
+ n = model ? model->n : 0;
fz_convert_color(ctx, model, colorfv, colorspace, color);
- for (i = 0; i < model->n; i++)
+ for (i = 0; i < n; i++)
colorbv[i] = colorfv[i] * 255;
colorbv[i] = alpha * 255;
@@ -738,13 +765,20 @@ fz_draw_clip_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
fz_try(ctx)
{
- mask = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ mask = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, mask);
- dest = fz_new_pixmap_with_bbox(ctx, model, &bbox);
- fz_clear_pixmap(ctx, dest);
+ /* When there is no alpha in the current destination (state[0].dest->alpha == 0)
+ * we have a choice. We can either create the new destination WITH alpha, or
+ * we can copy the old pixmap contents in. We opt for the latter here, but
+ * may want to revisit this decision in future. */
+ dest = fz_new_pixmap_with_bbox(ctx, model, &bbox, state[0].dest->alpha);
+ if (state[0].dest->alpha)
+ fz_clear_pixmap(ctx, dest);
+ else
+ fz_copy_pixmap_rect(ctx, dest, state[0].dest, &bbox);
if (state->shape)
{
- shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, shape);
}
else
@@ -775,7 +809,7 @@ fz_draw_clip_text(fz_context *ctx, fz_device *devp, const fz_text *text, const f
tm.f = span->items[i].y;
fz_concat(&trm, &tm, ctm);
- glyph = fz_render_glyph(ctx, span->font, gid, &trm, model, &state->scissor);
+ glyph = fz_render_glyph(ctx, span->font, gid, &trm, model, &state->scissor, state[1].dest->alpha);
if (glyph)
{
int x = (int)trm.e;
@@ -853,13 +887,20 @@ fz_draw_clip_stroke_text(fz_context *ctx, fz_device *devp, const fz_text *text,
fz_try(ctx)
{
- state[1].mask = mask = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].mask = mask = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, mask);
- state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, model, &bbox);
- fz_clear_pixmap(ctx, dest);
+ /* When there is no alpha in the current destination (state[0].dest->alpha == 0)
+ * we have a choice. We can either create the new destination WITH alpha, or
+ * we can copy the old pixmap contents in. We opt for the latter here, but
+ * may want to revisit this decision in future. */
+ state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, model, &bbox, state[0].dest->alpha);
+ if (state[0].dest->alpha)
+ fz_clear_pixmap(ctx, state[1].dest);
+ else
+ fz_copy_pixmap_rect(ctx, state[1].dest, state[0].dest, &bbox);
if (state->shape)
{
- state[1].shape = shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].shape = shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, shape);
}
else
@@ -963,12 +1004,6 @@ fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_m
if (fz_is_empty_irect(&bbox))
return;
- if (!model)
- {
- fz_warn(ctx, "cannot render shading directly to an alpha mask");
- return;
- }
-
if (state->blendmode & FZ_BLEND_KNOCKOUT)
state = fz_knockout_begin(ctx, dev);
@@ -977,11 +1012,14 @@ fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_m
if (alpha < 1)
{
- dest = fz_new_pixmap_with_bbox(ctx, state->dest->colorspace, &bbox);
- fz_clear_pixmap(ctx, dest);
+ dest = fz_new_pixmap_with_bbox(ctx, state->dest->colorspace, &bbox, state->dest->alpha);
+ if (state->dest->alpha)
+ fz_clear_pixmap(ctx, dest);
+ else
+ fz_copy_pixmap_rect(ctx, dest, state[0].dest, &bbox);
if (shape)
{
- shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, shape);
}
}
@@ -990,15 +1028,16 @@ fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_m
{
unsigned char *s;
int x, y, n, i;
+ n = model ? model->n : 0;
fz_convert_color(ctx, model, colorfv, shade->colorspace, shade->background);
- for (i = 0; i < model->n; i++)
+ for (i = 0; i < n; i++)
colorbv[i] = colorfv[i] * 255;
colorbv[i] = 255;
n = dest->n;
for (y = scissor.y0; y < scissor.y1; y++)
{
- s = dest->samples + (unsigned int)(((scissor.x0 - dest->x) + (y - dest->y) * dest->w) * dest->n);
+ s = dest->samples + (unsigned int)((y - dest->y) * dest->stride + (scissor.x0 - dest->x) * n);
for (x = scissor.x0; x < scissor.x1; x++)
{
for (i = 0; i < n; i++)
@@ -1009,7 +1048,7 @@ fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_m
{
for (y = scissor.y0; y < scissor.y1; y++)
{
- s = shape->samples + (unsigned int)((scissor.x0 - shape->x) + (y - shape->y) * shape->w);
+ s = shape->samples + (unsigned int)((y - shape->y) * shape->stride + (scissor.x0 - shape->x));
for (x = scissor.x0; x < scissor.x1; x++)
{
*s++ = 255;
@@ -1022,6 +1061,14 @@ fz_draw_fill_shade(fz_context *ctx, fz_device *devp, fz_shade *shade, const fz_m
if (shape)
fz_clear_pixmap_rect_with_value(ctx, shape, 255, &bbox);
+#ifdef DUMP_GROUP_BLENDS
+ dump_spaces(dev->top, "");
+ fz_dump_blend(ctx, dest, "Shade ");
+ if (shape)
+ fz_dump_blend(ctx, shape, "/");
+ printf("\n");
+#endif
+
if (alpha < 1)
{
fz_paint_pixmap(state->dest, dest, alpha * 255);
@@ -1122,12 +1169,6 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
fz_var(scaled);
- if (!model)
- {
- fz_warn(ctx, "cannot render image directly to an alpha mask");
- return;
- }
-
if (image->w == 0 || image->h == 0)
return;
@@ -1170,7 +1211,7 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
orig_pixmap = pixmap;
/* convert images with more components (cmyk->rgb) before scaling */
- /* convert images with fewer components (gray->rgb after scaling */
+ /* convert images with fewer components (gray->rgb) after scaling */
/* convert images with expensive colorspace transforms after scaling */
fz_try(ctx)
@@ -1186,7 +1227,7 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
{
fz_irect bbox;
fz_pixmap_bbox(ctx, pixmap, &bbox);
- converted = fz_new_pixmap_with_bbox(ctx, model, &bbox);
+ converted = fz_new_pixmap_with_bbox(ctx, model, &bbox, pixmap->alpha);
fz_convert_pixmap(ctx, converted, pixmap);
pixmap = converted;
}
@@ -1218,7 +1259,7 @@ fz_draw_fill_image(fz_context *ctx, fz_device *devp, fz_image *image, const fz_m
{
fz_irect bbox;
fz_pixmap_bbox(ctx, pixmap, &bbox);
- converted = fz_new_pixmap_with_bbox(ctx, model, &bbox);
+ converted = fz_new_pixmap_with_bbox(ctx, model, &bbox, pixmap->alpha);
fz_convert_pixmap(ctx, converted, pixmap);
pixmap = converted;
}
@@ -1252,7 +1293,7 @@ fz_draw_fill_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const
fz_pixmap *pixmap;
fz_pixmap *orig_pixmap;
int dx, dy;
- int i;
+ int i, n;
fz_draw_state *state = &dev->stack[dev->top];
fz_colorspace *model = state->dest->colorspace;
fz_irect clip;
@@ -1325,8 +1366,9 @@ fz_draw_fill_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const
pixmap = scaled;
}
+ n = model ? model->n : 0;
fz_convert_color(ctx, model, colorfv, colorspace, color);
- for (i = 0; i < model->n; i++)
+ for (i = 0; i < n; i++)
colorbv[i] = colorfv[i] * 255;
colorbv[i] = alpha * 255;
@@ -1404,14 +1446,21 @@ fz_draw_clip_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const
pixmap = fz_get_pixmap_from_image(ctx, image, NULL, &local_ctm, &dx, &dy);
orig_pixmap = pixmap;
- state[1].mask = mask = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].mask = mask = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, mask);
- state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, model, &bbox);
- fz_clear_pixmap(ctx, dest);
+ /* When there is no alpha in the current destination (state[0].dest->alpha == 0)
+ * we have a choice. We can either create the new destination WITH alpha, or
+ * we can copy the old pixmap contents in. We opt for the latter here, but
+ * may want to revisit this decision in future. */
+ state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, model, &bbox, state[0].dest->alpha);
+ if (state[0].dest->alpha)
+ fz_clear_pixmap(ctx, state[1].dest);
+ else
+ fz_copy_pixmap_rect(ctx, state[1].dest, state[0].dest, &bbox);
if (state->shape)
{
- state[1].shape = shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].shape = shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, shape);
}
@@ -1433,7 +1482,21 @@ fz_draw_clip_image_mask(fz_context *ctx, fz_device *devp, fz_image *image, const
if (scaled)
pixmap = scaled;
}
+#ifdef DUMP_GROUP_BLENDS
+ dump_spaces(dev->top, "");
+ fz_dump_blend(ctx, pixmap, "Plotting imagemask ");
+ fz_dump_blend(ctx, mask, "/");
+ fz_dump_blend(ctx, state[1].dest, " onto ");
+ if (state[1].shape)
+ fz_dump_blend(ctx, state[1].shape, "/");
+#endif
fz_paint_image(mask, &bbox, state->shape, pixmap, &local_ctm, 255, !(devp->hints & FZ_DONT_INTERPOLATE_IMAGES), devp->flags & FZ_DEVFLAG_GRIDFIT_AS_TILED);
+#ifdef DUMP_GROUP_BLENDS
+ fz_dump_blend(ctx, state[1].dest, " to get ");
+ if (state[1].shape)
+ fz_dump_blend(ctx, state[1].shape, "/");
+ printf("\n");
+#endif
}
fz_always(ctx)
{
@@ -1517,7 +1580,13 @@ fz_draw_begin_mask(fz_context *ctx, fz_device *devp, const fz_rect *rect, int lu
fz_try(ctx)
{
- state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, fz_device_gray(ctx), &bbox);
+ /* If luminosity, then we generate a mask from the greyscale value of the shapes.
+ * If !luminosity, then we generate a mask from the alpha value of the shapes.
+ */
+ if (luminosity)
+ state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, fz_device_gray(ctx), &bbox, 0);
+ else
+ state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
if (state->shape)
{
/* FIXME: If we ever want to support AIS true, then
@@ -1547,7 +1616,8 @@ fz_draw_begin_mask(fz_context *ctx, fz_device *devp, const fz_rect *rect, int lu
}
#ifdef DUMP_GROUP_BLENDS
- dump_spaces(dev->top-1, "Mask begin\n");
+ dump_spaces(dev->top-1, "Mask begin");
+ printf("%s\n", luminosity ? "(luminosity)" : "");
#endif
state[1].scissor = bbox;
state[1].luminosity = luminosity;
@@ -1578,7 +1648,10 @@ fz_draw_end_mask(fz_context *ctx, fz_device *devp)
luminosity = state[1].luminosity;
#ifdef DUMP_GROUP_BLENDS
- dump_spaces(dev->top-1, "Mask -> Clip\n");
+ dump_spaces(dev->top-1, "Mask -> Clip: ");
+ fz_dump_blend(ctx, state[1].dest, "Mask ");
+ if (state[1].shape)
+ fz_dump_blend(ctx, state[1].shape, "/");
#endif
fz_try(ctx)
{
@@ -1594,10 +1667,18 @@ fz_draw_end_mask(fz_context *ctx, fz_device *devp)
fz_drop_pixmap(ctx, state[1].shape);
state[1].shape = NULL;
+#ifdef DUMP_GROUP_BLENDS
+ fz_dump_blend(ctx, temp, "-> Clip ");
+ printf("\n");
+#endif
+
/* create new dest scratch buffer */
fz_pixmap_bbox(ctx, temp, &bbox);
- dest = fz_new_pixmap_with_bbox(ctx, state->dest->colorspace, &bbox);
- fz_clear_pixmap(ctx, dest);
+ dest = fz_new_pixmap_with_bbox(ctx, state->dest->colorspace, &bbox, state->dest->alpha);
+ if (state->dest->alpha)
+ fz_clear_pixmap(ctx, dest);
+ else
+ fz_copy_pixmap_rect(ctx, dest, state->dest, &bbox);
/* push soft mask as clip mask */
state[1].dest = dest;
@@ -1606,7 +1687,7 @@ fz_draw_end_mask(fz_context *ctx, fz_device *devp)
* clip mask when we pop. So create a new shape now. */
if (state[0].shape)
{
- state[1].shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, state[1].shape);
}
state[1].scissor = bbox;
@@ -1635,13 +1716,13 @@ fz_draw_begin_group(fz_context *ctx, fz_device *devp, const fz_rect *rect, int i
fz_try(ctx)
{
- state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, model, &bbox);
-
#ifndef ATTEMPT_KNOCKOUT_AND_ISOLATED
knockout = 0;
isolated = 1;
#endif
+ state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, model, &bbox, state[0].dest->alpha || isolated);
+
if (isolated)
{
fz_clear_pixmap(ctx, dest);
@@ -1659,7 +1740,7 @@ fz_draw_begin_group(fz_context *ctx, fz_device *devp, const fz_rect *rect, int i
}
else
{
- state[1].shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, state[1].shape);
}
@@ -1902,12 +1983,13 @@ fz_draw_begin_tile(fz_context *ctx, fz_device *devp, const fz_rect *area, const
fz_try(ctx)
{
- state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, model, &bbox);
+ /* Patterns can be transparent, so we need to have an alpha here. */
+ state[1].dest = dest = fz_new_pixmap_with_bbox(ctx, model, &bbox, 1);
fz_clear_pixmap(ctx, dest);
shape = state[0].shape;
if (shape)
{
- state[1].shape = shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox);
+ state[1].shape = shape = fz_new_pixmap_with_bbox(ctx, NULL, &bbox, 1);
fz_clear_pixmap(ctx, shape);
}
state[1].blendmode |= FZ_BLEND_ISOLATED;
diff --git a/source/fitz/draw-edge.c b/source/fitz/draw-edge.c
index 6c104ff2..abf02a8c 100644
--- a/source/fitz/draw-edge.c
+++ b/source/fitz/draw-edge.c
@@ -836,11 +836,11 @@ static inline void
blit_aa(fz_pixmap *dst, int x, int y, unsigned char *mp, int w, unsigned char *color)
{
unsigned char *dp;
- dp = dst->samples + (unsigned int)(( (y - dst->y) * dst->w + (x - dst->x) ) * dst->n);
+ dp = dst->samples + (unsigned int)((y - dst->y) * dst->stride + (x - dst->x) * dst->n);
if (color)
- fz_paint_span_with_color(dp, mp, dst->n, w, color);
+ fz_paint_span_with_color(dp, mp, dst->n, w, color, dst->alpha);
else
- fz_paint_span(dp, mp, 1, w, 255);
+ fz_paint_span(dp, dst->alpha, mp, 1, 0, w, 255);
}
static void
@@ -1031,15 +1031,16 @@ static inline void
blit_sharp(int x0, int x1, int y, const fz_irect *clip, fz_pixmap *dst, unsigned char *color)
{
unsigned char *dp;
+ int da = dst->alpha;
x0 = fz_clampi(x0, dst->x, dst->x + dst->w);
x1 = fz_clampi(x1, dst->x, dst->x + dst->w);
if (x0 < x1)
{
- dp = dst->samples + (unsigned int)(( (y - dst->y) * dst->w + (x0 - dst->x) ) * dst->n);
+ dp = dst->samples + (unsigned int)((y - dst->y) * dst->stride + (x0 - dst->x) * dst->n);
if (color)
- fz_paint_solid_color(dp, dst->n, x1 - x0, color);
+ fz_paint_solid_color(dp, dst->n, x1 - x0, color, da);
else
- fz_paint_solid_alpha(dp, x1 - x0, 255);
+ memset(dp, 255, x1-x0);
}
}
diff --git a/source/fitz/draw-glyph.c b/source/fitz/draw-glyph.c
index 691e426d..98f9252b 100644
--- a/source/fitz/draw-glyph.c
+++ b/source/fitz/draw-glyph.c
@@ -185,7 +185,7 @@ fz_render_stroked_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix *trm,
(void)fz_subpixel_adjust(ctx, trm, &subpix_trm, &qe, &qf);
return fz_render_ft_stroked_glyph(ctx, font, gid, &subpix_trm, ctm, stroke);
}
- return fz_render_glyph(ctx, font, gid, trm, NULL, scissor);
+ return fz_render_glyph(ctx, font, gid, trm, NULL, scissor, 1);
}
fz_pixmap *
@@ -201,7 +201,7 @@ fz_render_stroked_glyph_pixmap(fz_context *ctx, fz_font *font, int gid, fz_matri
(void)fz_subpixel_adjust(ctx, trm, &subpix_trm, &qe, &qf);
return fz_render_ft_stroked_glyph_pixmap(ctx, font, gid, &subpix_trm, ctm, stroke);
}
- return fz_render_glyph_pixmap(ctx, font, gid, trm, NULL, scissor);
+ return fz_render_glyph_pixmap(ctx, font, gid, trm, scissor);
}
static unsigned do_hash(unsigned char *s, int len)
@@ -241,7 +241,7 @@ move_to_front(fz_glyph_cache *cache, fz_glyph_cache_entry *entry)
}
fz_glyph *
-fz_render_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix *ctm, fz_colorspace *model, const fz_irect *scissor)
+fz_render_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix *ctm, fz_colorspace *model, const fz_irect *scissor, int alpha)
{
fz_glyph_cache *cache;
fz_glyph_key key;
@@ -407,7 +407,7 @@ unlock_and_return_val:
}
fz_pixmap *
-fz_render_glyph_pixmap(fz_context *ctx, fz_font *font, int gid, fz_matrix *ctm, fz_colorspace *model, const fz_irect *scissor)
+fz_render_glyph_pixmap(fz_context *ctx, fz_font *font, int gid, fz_matrix *ctm, const fz_irect *scissor)
{
fz_pixmap *val;
unsigned char qe, qf;
@@ -432,7 +432,7 @@ fz_render_glyph_pixmap(fz_context *ctx, fz_font *font, int gid, fz_matrix *ctm,
}
else if (font->t3procs)
{
- val = fz_render_t3_glyph_pixmap(ctx, font, gid, &subpix_ctm, model, scissor);
+ val = fz_render_t3_glyph_pixmap(ctx, font, gid, &subpix_ctm, NULL, scissor);
}
else
{
diff --git a/source/fitz/draw-imp.h b/source/fitz/draw-imp.h
index 18580585..0eef8156 100644
--- a/source/fitz/draw-imp.h
+++ b/source/fitz/draw-imp.h
@@ -29,11 +29,10 @@ fz_irect *fz_bound_path_accurate(fz_context *ctx, fz_irect *bbox, const fz_irect
* Plotting functions.
*/
-void fz_paint_solid_alpha(unsigned char * restrict dp, int w, int alpha);
-void fz_paint_solid_color(unsigned char * restrict dp, int n, int w, unsigned char *color);
+void fz_paint_solid_color(unsigned char * restrict dp, int n, int w, unsigned char *color, int da);
-void fz_paint_span(unsigned char * restrict dp, unsigned char * restrict sp, int n, int w, int alpha);
-void fz_paint_span_with_color(unsigned char * restrict dp, unsigned char * restrict mp, int n, int w, unsigned char *color);
+void fz_paint_span(unsigned char * restrict dp, int da, unsigned char * restrict sp, int sa, int n, int w, int alpha);
+void fz_paint_span_with_color(unsigned char * restrict dp, unsigned char * restrict mp, int n, int w, unsigned char *color, int da);
void fz_paint_image(fz_pixmap *dst, const fz_irect *scissor, fz_pixmap *shape, fz_pixmap *img, const fz_matrix *ctm, int alpha, int lerp_allowed, int gridfit_as_tiled);
void fz_paint_image_with_color(fz_pixmap *dst, const fz_irect *scissor, fz_pixmap *shape, fz_pixmap *img, const fz_matrix *ctm, unsigned char *colorbv, int lerp_allowed, int gridfit_as_tiled);
diff --git a/source/fitz/draw-mesh.c b/source/fitz/draw-mesh.c
index 00483f51..c4e54643 100644
--- a/source/fitz/draw-mesh.c
+++ b/source/fitz/draw-mesh.c
@@ -9,7 +9,7 @@ static void paint_scan(fz_pixmap *restrict pix, int y, int fx0, int fx1, int cx0
int c[MAXN], dc[MAXN];
int k, w;
float div, mul;
- int x0, x1;
+ int x0, x1, pa;
/* Ensure that fx0 is left edge, and fx1 is right */
if (fx0 > fx1)
@@ -41,7 +41,8 @@ static void paint_scan(fz_pixmap *restrict pix, int y, int fx0, int fx1, int cx0
c[k] = v0[k] + dc[k] * mul;
}
- p = pix->samples + ((x0 - pix->x) + (y - pix->y) * pix->w) * pix->n;
+ p = pix->samples + ((x0 - pix->x) * pix->n) + ((y - pix->y) * pix->stride);
+ pa = pix->alpha;
while (w--)
{
for (k = 0; k < n; k++)
@@ -49,7 +50,8 @@ static void paint_scan(fz_pixmap *restrict pix, int y, int fx0, int fx1, int cx0
*p++ = c[k]>>16;
c[k] += dc[k];
}
- *p++ = 255;
+ if (pa)
+ *p++ = 255;
}
}
@@ -205,7 +207,7 @@ fz_paint_shade(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_pixmap
fz_pixmap *conv = NULL;
float color[FZ_MAX_COLORS];
struct paint_tri_data ptd = { 0 };
- int i, k;
+ int i, k, n;
fz_matrix local_ctm;
fz_var(temp);
@@ -218,16 +220,19 @@ fz_paint_shade(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_pixmap
if (shade->use_function)
{
fz_color_converter cc;
+ n = dest->colorspace ? dest->colorspace->n : 0;
fz_lookup_color_converter(ctx, &cc, dest->colorspace, shade->colorspace);
for (i = 0; i < 256; i++)
{
cc.convert(ctx, &cc, color, shade->function[i]);
- for (k = 0; k < dest->colorspace->n; k++)
+ for (k = 0; k < n; k++)
clut[i][k] = color[k] * 255;
clut[i][k] = shade->function[i][shade->colorspace->n] * 255;
}
- conv = fz_new_pixmap_with_bbox(ctx, dest->colorspace, bbox);
- temp = fz_new_pixmap_with_bbox(ctx, fz_device_gray(ctx), bbox);
+ /* We need to use alpha = 1 here, because the shade might not fill
+ * the bbox. */
+ conv = fz_new_pixmap_with_bbox(ctx, dest->colorspace, bbox, 1);
+ temp = fz_new_pixmap_with_bbox(ctx, fz_device_gray(ctx), bbox, 1);
fz_clear_pixmap(ctx, temp);
}
else
@@ -246,14 +251,25 @@ fz_paint_shade(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_pixmap
{
unsigned char *s = temp->samples;
unsigned char *d = conv->samples;
- int len = temp->w * temp->h;
- while (len--)
+ int da = conv->alpha;
+ int sa = temp->alpha;
+ int hh = temp->h;
+ while (hh--)
{
- int v = *s++;
- int a = fz_mul255(*s++, clut[v][conv->n - 1]);
- for (k = 0; k < conv->n - 1; k++)
- *d++ = fz_mul255(clut[v][k], a);
- *d++ = a;
+ int len = temp->w;
+ while (len--)
+ {
+ int v = *s++;
+ int a = (da ? clut[v][conv->n - 1] : 255);
+ if (sa)
+ a = fz_mul255(*s++, a);
+ for (k = 0; k < conv->n - da; k++)
+ *d++ = fz_mul255(clut[v][k], a);
+ if (da)
+ *d++ = a;
+ }
+ d += conv->stride - conv->w * conv->n;
+ s += temp->stride - temp->w * temp->n;
}
fz_paint_pixmap(dest, conv, 255);
fz_drop_pixmap(ctx, conv);
diff --git a/source/fitz/draw-paint.c b/source/fitz/draw-paint.c
index acd4c0cb..17f50724 100644
--- a/source/fitz/draw-paint.c
+++ b/source/fitz/draw-paint.c
@@ -75,19 +75,8 @@ typedef unsigned char byte;
/* These are used by the non-aa scan converter */
-void
-fz_paint_solid_alpha(byte * restrict dp, int w, int alpha)
-{
- int t = FZ_EXPAND(255 - alpha);
- while (w--)
- {
- *dp = alpha + FZ_COMBINE(*dp, t);
- dp ++;
- }
-}
-
static inline void
-fz_paint_solid_color_2(byte * restrict dp, int w, byte *color)
+fz_paint_solid_color_2_da(byte * restrict dp, int w, byte *color)
{
int sa = FZ_EXPAND(color[1]);
if (sa == 0)
@@ -119,7 +108,7 @@ static inline int isbigendian(void)
}
static inline void
-fz_paint_solid_color_4(byte * restrict dp, int w, byte *color)
+fz_paint_solid_color_4_da(byte * restrict dp, int w, byte *color)
{
unsigned int rgba = *(int *)color;
int sa = FZ_EXPAND(color[3]);
@@ -158,7 +147,7 @@ fz_paint_solid_color_4(byte * restrict dp, int w, byte *color)
}
static inline void
-fz_paint_solid_color_5(byte * restrict dp, int w, byte *color)
+fz_paint_solid_color_5_da(byte * restrict dp, int w, byte *color)
{
int sa = FZ_EXPAND(color[4]);
if (sa == 0)
@@ -236,10 +225,10 @@ fz_paint_solid_color_5(byte * restrict dp, int w, byte *color)
}
static inline void
-fz_paint_solid_color_N(byte * restrict dp, int n, int w, byte *color)
+fz_paint_solid_color_N(byte * restrict dp, int n, int w, byte *color, int da)
{
int k;
- int n1 = n - 1;
+ int n1 = n - da;
int sa = FZ_EXPAND(color[n1]);
if (sa == 0)
return;
@@ -249,7 +238,8 @@ fz_paint_solid_color_N(byte * restrict dp, int n, int w, byte *color)
{
for (k = 0; k < n1; k++)
dp[k] = color[k];
- dp[k] = 255;
+ if (da)
+ dp[k] = 255;
dp += n;
}
}
@@ -259,28 +249,42 @@ fz_paint_solid_color_N(byte * restrict dp, int n, int w, byte *color)
{
for (k = 0; k < n1; k++)
dp[k] = FZ_BLEND(color[k], dp[k], sa);
- dp[k] = FZ_BLEND(255, dp[k], sa);
+ if (da)
+ dp[k] = FZ_BLEND(255, dp[k], sa);
dp += n;
}
}
}
void
-fz_paint_solid_color(byte * restrict dp, int n, int w, byte *color)
+fz_paint_solid_color(byte * restrict dp, int n, int w, byte *color, int da)
{
- switch (n)
+ if (da)
{
- case 2: fz_paint_solid_color_2(dp, w, color); break;
- case 4: fz_paint_solid_color_4(dp, w, color); break;
- case 5: fz_paint_solid_color_5(dp, w, color); break;
- default: fz_paint_solid_color_N(dp, n, w, color); break;
+ switch (n)
+ {
+ case 2: fz_paint_solid_color_2_da(dp, w, color); break;
+ case 4: fz_paint_solid_color_4_da(dp, w, color); break;
+ case 5: fz_paint_solid_color_5_da(dp, w, color); break;
+ default: fz_paint_solid_color_N(dp, n, w, color, 1); break;
+ }
+ }
+ else
+ {
+ switch (n)
+ {
+ case 1: fz_paint_solid_color_N(dp, 1, w, color, 0); break;
+ case 3: fz_paint_solid_color_N(dp, 3, w, color, 0); break;
+ case 4: fz_paint_solid_color_N(dp, 4, w, color, 0); break;
+ default: fz_paint_solid_color_N(dp, n, w, color, 0); break;
+ }
}
}
/* Blend a non-premultiplied color in mask over destination */
static inline void
-fz_paint_span_with_color_2(byte * restrict dp, byte * restrict mp, int w, byte *color)
+fz_paint_span_with_color_2_da(byte * restrict dp, byte * restrict mp, int w, byte *color)
{
int sa = FZ_EXPAND(color[1]);
int g = color[0];
@@ -327,7 +331,7 @@ fz_paint_span_with_color_2(byte * restrict dp, byte * restrict mp, int w, byte *
}
static inline void
-fz_paint_span_with_color_4(byte * restrict dp, byte * restrict mp, int w, byte *color)
+fz_paint_span_with_color_4_da(byte * restrict dp, byte * restrict mp, int w, byte *color)
{
unsigned int rgba = *((unsigned int *)color);
unsigned int mask, rb, ga;
@@ -391,7 +395,7 @@ fz_paint_span_with_color_4(byte * restrict dp, byte * restrict mp, int w, byte *
}
static inline void
-fz_paint_span_with_color_5(byte * restrict dp, byte * restrict mp, int w, byte *color)
+fz_paint_span_with_color_5_da(byte * restrict dp, byte * restrict mp, int w, byte *color)
{
int sa = FZ_EXPAND(color[4]);
int c = color[0];
@@ -450,10 +454,10 @@ fz_paint_span_with_color_5(byte * restrict dp, byte * restrict mp, int w, byte *
}
static inline void
-fz_paint_span_with_color_N(byte * restrict dp, byte * restrict mp, int n, int w, byte *color)
+fz_paint_span_with_color_N(byte * restrict dp, byte * restrict mp, int n, int w, byte *color, int da)
{
int k;
- int n1 = n - 1;
+ int n1 = n - da;
int sa = FZ_EXPAND(color[n1]);
if (sa == 0)
return;
@@ -470,13 +474,15 @@ fz_paint_span_with_color_N(byte * restrict dp, byte * restrict mp, int n, int w,
{
for (k = 0; k < n1; k++)
dp[k] = color[k];
- dp[k] = 255;
+ if (da)
+ dp[k] = 255;
}
else
{
for (k = 0; k < n1; k++)
dp[k] = FZ_BLEND(color[k], dp[k], ma);
- dp[k] = FZ_BLEND(255, dp[k], ma);
+ if (da)
+ dp[k] = FZ_BLEND(255, dp[k], ma);
}
dp += n;
}
@@ -489,21 +495,35 @@ fz_paint_span_with_color_N(byte * restrict dp, byte * restrict mp, int n, int w,
ma = FZ_COMBINE(FZ_EXPAND(ma), sa);
for (k = 0; k < n1; k++)
dp[k] = FZ_BLEND(color[k], dp[k], ma);
- dp[k] = FZ_BLEND(255, dp[k], ma);
+ if (da)
+ dp[k] = FZ_BLEND(255, dp[k], ma);
dp += n;
}
}
}
void
-fz_paint_span_with_color(byte * restrict dp, byte * restrict mp, int n, int w, byte *color)
+fz_paint_span_with_color(byte * restrict dp, byte * restrict mp, int n, int w, byte *color, int da)
{
- switch (n)
+ if (da)
+ {
+ switch (n)
+ {
+ case 2: fz_paint_span_with_color_2_da(dp, mp, w, color); break;
+ case 4: fz_paint_span_with_color_4_da(dp, mp, w, color); break;
+ case 5: fz_paint_span_with_color_5_da(dp, mp, w, color); break;
+ default: fz_paint_span_with_color_N(dp, mp, n, w, color, 1); break;
+ }
+ }
+ else
{
- case 2: fz_paint_span_with_color_2(dp, mp, w, color); break;
- case 4: fz_paint_span_with_color_4(dp, mp, w, color); break;
- case 5: fz_paint_span_with_color_5(dp, mp, w, color); break;
- default: fz_paint_span_with_color_N(dp, mp, n, w, color); break;
+ switch (n)
+ {
+ case 1: fz_paint_span_with_color_N(dp, mp, 1, w, color, 0); break;
+ case 3: fz_paint_span_with_color_N(dp, mp, 3, w, color, 0); break;
+ case 4: fz_paint_span_with_color_N(dp, mp, 4, w, color, 0); break;
+ default: fz_paint_span_with_color_N(dp, mp, n, w, color, 0); break;
+ }
}
}
@@ -511,7 +531,7 @@ fz_paint_span_with_color(byte * restrict dp, byte * restrict mp, int n, int w, b
/* FIXME: There is potential for SWAR optimisation here */
static inline void
-fz_paint_span_with_mask_2(byte * restrict dp, byte * restrict sp, byte * restrict mp, int w)
+fz_paint_span_with_mask_1(byte * restrict dp, int da, byte * restrict sp, int sa, byte * restrict mp, int w)
{
while (w--)
{
@@ -520,42 +540,65 @@ fz_paint_span_with_mask_2(byte * restrict dp, byte * restrict sp, byte * restric
ma = FZ_EXPAND(ma);
if (ma == 0)
{
- dp += 2;
- sp += 2;
+ dp += 1 + da;
+ sp += 1 + sa;
}
else if (ma == 256)
{
- masa = 255 - sp[1];
+ masa = (sa ? 255 - sp[1] : 0);
if (masa == 0)
{
*dp++ = *sp++;
- *dp++ = *sp++;
+ if (da)
+ *dp++ = (sa ? *sp++ : 255);
}
else
{
masa = FZ_EXPAND(masa);
*dp = *sp + FZ_COMBINE(*dp, masa);
sp++; dp++;
- *dp = *sp + FZ_COMBINE(*dp, masa);
- sp++; dp++;
+ if (da)
+ {
+ *dp = (sa ? *sp : 255) + FZ_COMBINE(*dp, masa);
+ dp++;
+ }
+ if (sa)
+ sp++;
}
}
else
{
- masa = FZ_COMBINE(sp[1], ma);
- masa = 255 - masa;
- masa = FZ_EXPAND(masa);
- *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
- sp++; dp++;
- *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
- sp++; dp++;
+ if (sa)
+ {
+ masa = FZ_COMBINE(sp[1], ma);
+ masa = 255 - masa;
+ masa = FZ_EXPAND(masa);
+ *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
+ sp++; dp++;
+ if (da)
+ {
+ *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
+ dp++;
+ }
+ sp++;
+ }
+ else
+ {
+ *dp = FZ_BLEND(*sp, *dp, ma);
+ sp++; dp++;
+ if (da)
+ {
+ *dp = FZ_BLEND(255, *dp, ma);
+ dp++;
+ }
+ }
}
}
}
/* FIXME: There is potential for SWAR optimisation here */
static inline void
-fz_paint_span_with_mask_4(byte * restrict dp, byte * restrict sp, byte * restrict mp, int w)
+fz_paint_span_with_mask_3(byte * restrict dp, int da, byte * restrict sp, int sa, byte * restrict mp, int w)
{
while (w--)
{
@@ -564,16 +607,29 @@ fz_paint_span_with_mask_4(byte * restrict dp, byte * restrict sp, byte * restric
ma = FZ_EXPAND(ma);
if (ma == 0)
{
- dp += 4;
- sp += 4;
+ dp += 3 + da;
+ sp += 3 + sa;
}
else if (ma == 256)
{
- masa = 255 - sp[3];
+ masa = (sa ? 255 - sp[3] : 0);
if (masa == 0)
{
- *(int*)dp = *(int *)sp;
- sp += 4; dp += 4;
+ if (da && sa)
+ {
+ *(int*)dp = *(int *)sp;
+ sp += 4; dp += 4;
+ }
+ else
+ {
+ *dp++ = *sp++;
+ *dp++ = *sp++;
+ *dp++ = *sp++;
+ if (da)
+ *dp++ = (sa ? *sp : 255);
+ if (sa)
+ sp++;
+ }
}
else
{
@@ -584,31 +640,57 @@ fz_paint_span_with_mask_4(byte * restrict dp, byte * restrict sp, byte * restric
sp++; dp++;
*dp = *sp + FZ_COMBINE(*dp, masa);
sp++; dp++;
- *dp = *sp + FZ_COMBINE(*dp, masa);
- sp++; dp++;
+ if (da)
+ {
+ *dp = (sa ? *sp : 255) + FZ_COMBINE(*dp, masa);
+ dp++;
+ }
+ if (sa)
+ sp++;
}
}
else
{
/* FIXME: There is potential for SWAR optimisation here */
- masa = FZ_COMBINE(sp[3], ma);
- masa = 255 - masa;
- masa = FZ_EXPAND(masa);
- *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
- sp++; dp++;
- *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
- sp++; dp++;
- *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
- sp++; dp++;
- *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
- sp++; dp++;
+ if (sa)
+ {
+ masa = FZ_COMBINE(sp[3], ma);
+ masa = 255 - masa;
+ masa = FZ_EXPAND(masa);
+ *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
+ sp++; dp++;
+ *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
+ sp++; dp++;
+ *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
+ sp++; dp++;
+ if (da)
+ {
+ *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
+ dp++;
+ }
+ sp++;
+ }
+ else
+ {
+ *dp = FZ_BLEND(*sp, *dp, ma);
+ sp++; dp++;
+ *dp = FZ_BLEND(*sp, *dp, ma);
+ sp++; dp++;
+ *dp = FZ_BLEND(*sp, *dp, ma);
+ sp++; dp++;
+ if (da)
+ {
+ *dp = FZ_BLEND(255, *dp, ma);
+ dp++;
+ }
+ }
}
}
}
/* FIXME: There is potential for SWAR optimisation here */
static inline void
-fz_paint_span_with_mask_5(byte * restrict dp, byte * restrict sp, byte * restrict mp, int w)
+fz_paint_span_with_mask_4(byte * restrict dp, int da, byte * restrict sp, int sa, byte * restrict mp, int w)
{
while (w--)
{
@@ -617,19 +699,22 @@ fz_paint_span_with_mask_5(byte * restrict dp, byte * restrict sp, byte * restric
ma = FZ_EXPAND(ma);
if (ma == 0)
{
- dp += 5;
- sp += 5;
+ dp += 4 + da;
+ sp += 4 + sa;
}
else if (ma == 256)
{
- masa = 255 - sp[4];
+ masa = (sa ? 255 - sp[4] : 0);
if (masa == 0)
{
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
- *dp++ = *sp++;
+ if (da)
+ *dp++ = (sa ? *sp : 255);
+ if (sa)
+ sp++;
}
else
{
@@ -642,31 +727,59 @@ fz_paint_span_with_mask_5(byte * restrict dp, byte * restrict sp, byte * restric
sp++; dp++;
*dp = *sp + FZ_COMBINE(*dp, masa);
sp++; dp++;
- *dp = *sp + FZ_COMBINE(*dp, masa);
- sp++; dp++;
+ if (da)
+ {
+ *dp = (sa ? *sp : 255) + FZ_COMBINE(*dp, masa);
+ dp++;
+ }
+ if (sa)
+ sp++;
}
}
else
{
- masa = FZ_COMBINE(sp[4], ma);
- masa = 255 - masa;
- masa = FZ_EXPAND(masa);
- *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
- sp++; dp++;
- *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
- sp++; dp++;
- *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
- sp++; dp++;
- *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
- sp++; dp++;
- *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
- sp++; dp++;
+ if (sa)
+ {
+ masa = FZ_COMBINE(sp[4], ma);
+ masa = 255 - masa;
+ masa = FZ_EXPAND(masa);
+ *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
+ sp++; dp++;
+ *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
+ sp++; dp++;
+ *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
+ sp++; dp++;
+ *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
+ sp++; dp++;
+ if (da)
+ {
+ *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
+ dp++;
+ }
+ sp++;
+ }
+ else
+ {
+ *dp = FZ_BLEND(*sp, *dp, ma);
+ sp++; dp++;
+ *dp = FZ_BLEND(*sp, *dp, ma);
+ sp++; dp++;
+ *dp = FZ_BLEND(*sp, *dp, ma);
+ sp++; dp++;
+ *dp = FZ_BLEND(*sp, *dp, ma);
+ sp++; dp++;
+ if (da)
+ {
+ *dp = FZ_BLEND(255, *dp, ma);
+ dp++;
+ }
+ }
}
}
}
static inline void
-fz_paint_span_with_mask_N(byte * restrict dp, byte * restrict sp, byte * restrict mp, int n, int w)
+fz_paint_span_with_mask_N(byte * restrict dp, int da, byte * restrict sp, int sa, byte * restrict mp, int n, int w)
{
while (w--)
{
@@ -674,19 +787,23 @@ fz_paint_span_with_mask_N(byte * restrict dp, byte * restrict sp, byte * restric
ma = FZ_EXPAND(ma);
if (ma == 0)
{
- dp += n;
- sp += n;
+ dp += n + da;
+ sp += n + sa;
}
else if (ma == 256)
{
int k = n;
- int masa = 255 - sp[n-1];
+ int masa = (sa ? 255 - sp[n] : 0);
if (masa == 0)
{
while (k--)
{
*dp++ = *sp++;
}
+ if (da)
+ *dp++ = (sa ? *sp : 255);
+ if (sa)
+ sp++;
}
else
{
@@ -696,78 +813,158 @@ fz_paint_span_with_mask_N(byte * restrict dp, byte * restrict sp, byte * restric
*dp = *sp + FZ_COMBINE(*dp, masa);
sp++; dp++;
}
+ if (da)
+ {
+ *dp = (sa ? *sp : 255) + FZ_COMBINE(*dp, masa);
+ dp++;
+ }
+ if (sa)
+ sp++;
}
}
else
{
int k = n;
- int masa = FZ_COMBINE(sp[n-1], ma);
- masa = 255-masa;
- masa = FZ_EXPAND(masa);
- while (k--)
+ if (sa)
{
- *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
- sp++; dp++;
+ int masa;
+ masa = FZ_COMBINE(sp[n], ma);
+ masa = 255-masa;
+ masa = FZ_EXPAND(masa);
+ while (k--)
+ {
+ *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
+ sp++; dp++;
+ }
+ if (da)
+ {
+ *dp = FZ_COMBINE2(*sp, ma, *dp, masa);
+ dp++;
+ }
+ sp++;
+ }
+ else
+ {
+ while (k--)
+ {
+ *dp = FZ_BLEND(*sp, *dp, ma);
+ sp++; dp++;
+ }
+ if (da)
+ {
+ *dp = FZ_BLEND(255, *dp, ma);
+ dp++;
+ }
}
}
}
}
static void
-fz_paint_span_with_mask(byte * restrict dp, byte * restrict sp, byte * restrict mp, int n, int w)
+fz_paint_span_with_mask(byte * restrict dp, int da, byte * restrict sp, int sa, byte * restrict mp, int n, int w)
{
- switch (n)
+ if (da)
+ {
+ if (sa)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_span_with_mask_1(dp, 1, sp, 1, mp, w); break;
+ case 3: fz_paint_span_with_mask_3(dp, 1, sp, 1, mp, w); break;
+ case 4: fz_paint_span_with_mask_4(dp, 1, sp, 1, mp, w); break;
+ default: fz_paint_span_with_mask_N(dp, 1, sp, 1, mp, n, w); break;
+ }
+ }
+ else
+ {
+ switch (n)
+ {
+ case 1: fz_paint_span_with_mask_1(dp, 1, sp, 0, mp, w); break;
+ case 3: fz_paint_span_with_mask_3(dp, 1, sp, 0, mp, w); break;
+ case 4: fz_paint_span_with_mask_4(dp, 1, sp, 0, mp, w); break;
+ default: fz_paint_span_with_mask_N(dp, 1, sp, 0, mp, n, w); break;
+ }
+ }
+ }
+ else
{
- case 2: fz_paint_span_with_mask_2(dp, sp, mp, w); break;
- case 4: fz_paint_span_with_mask_4(dp, sp, mp, w); break;
- case 5: fz_paint_span_with_mask_5(dp, sp, mp, w); break;
- default: fz_paint_span_with_mask_N(dp, sp, mp, n, w); break;
+ if (sa)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_span_with_mask_1(dp, 0, sp, 1, mp, w); break;
+ case 3: fz_paint_span_with_mask_3(dp, 0, sp, 1, mp, w); break;
+ case 4: fz_paint_span_with_mask_4(dp, 0, sp, 1, mp, w); break;
+ default: fz_paint_span_with_mask_N(dp, 0, sp, 1, mp, n, w); break;
+ }
+ }
+ else
+ {
+ switch (n)
+ {
+ case 1: fz_paint_span_with_mask_1(dp, 0, sp, 0, mp, w); break;
+ case 3: fz_paint_span_with_mask_3(dp, 0, sp, 0, mp, w); break;
+ case 4: fz_paint_span_with_mask_4(dp, 0, sp, 0, mp, w); break;
+ default: fz_paint_span_with_mask_N(dp, 0, sp, 0, mp, n, w); break;
+ }
+ }
}
}
/* Blend source in constant alpha over destination */
static inline void
-fz_paint_span_2_with_alpha(byte * restrict dp, byte * restrict sp, int w, int alpha)
+fz_paint_span_1_with_alpha(byte * restrict dp, int da, byte * restrict sp, int sa, int w, int alpha)
{
- alpha = FZ_EXPAND(alpha);
+ if (sa)
+ alpha = FZ_EXPAND(alpha);
while (w--)
{
- int masa = FZ_COMBINE(sp[1], alpha);
- *dp = FZ_BLEND(*sp, *dp, masa);
- dp++; sp++;
+ int masa = (sa ? FZ_COMBINE(sp[1], alpha) : alpha);
*dp = FZ_BLEND(*sp, *dp, masa);
dp++; sp++;
+ if (da)
+ {
+ *dp = FZ_BLEND((sa ? *sp : 255), *dp, masa);
+ dp++;
+ }
+ if (sa)
+ sp++;
}
}
static inline void
-fz_paint_span_4_with_alpha(byte * restrict dp, byte * restrict sp, int w, int alpha)
+fz_paint_span_3_with_alpha(byte * restrict dp, int da, byte * restrict sp, int sa, int w, int alpha)
{
- alpha = FZ_EXPAND(alpha);
+ if (sa)
+ alpha = FZ_EXPAND(alpha);
while (w--)
{
- int masa = FZ_COMBINE(sp[3], alpha);
- *dp = FZ_BLEND(*sp, *dp, masa);
- sp++; dp++;
+ int masa = (sa ? FZ_COMBINE(sp[3], alpha) : alpha);
*dp = FZ_BLEND(*sp, *dp, masa);
sp++; dp++;
*dp = FZ_BLEND(*sp, *dp, masa);
sp++; dp++;
*dp = FZ_BLEND(*sp, *dp, masa);
sp++; dp++;
+ if (da)
+ {
+ *dp = FZ_BLEND((sa ? *sp : 255), *dp, masa);
+ dp++;
+ }
+ if (sa)
+ sp++;
}
}
static inline void
-fz_paint_span_5_with_alpha(byte * restrict dp, byte * restrict sp, int w, int alpha)
+fz_paint_span_4_with_alpha(byte * restrict dp, int da, byte * restrict sp, int sa, int w, int alpha)
{
- alpha = FZ_EXPAND(alpha);
+ if (sa)
+ alpha = FZ_EXPAND(alpha);
while (w--)
{
- int masa = FZ_COMBINE(sp[4], alpha);
- *dp = FZ_BLEND(*sp, *dp, masa);
- sp++; dp++;
+ int masa = (sa ? FZ_COMBINE(sp[4], alpha) : alpha);
*dp = FZ_BLEND(*sp, *dp, masa);
sp++; dp++;
*dp = FZ_BLEND(*sp, *dp, masa);
@@ -776,29 +973,44 @@ fz_paint_span_5_with_alpha(byte * restrict dp, byte * restrict sp, int w, int al
sp++; dp++;
*dp = FZ_BLEND(*sp, *dp, masa);
sp++; dp++;
+ if (da)
+ {
+ *dp = FZ_BLEND((sa ? *sp : 255), *dp, masa);
+ dp++;
+ }
+ if (sa)
+ sp++;
}
}
static inline void
-fz_paint_span_N_with_alpha(byte * restrict dp, byte * restrict sp, int n, int w, int alpha)
+fz_paint_span_N_with_alpha(byte * restrict dp, int da, byte * restrict sp, int sa, int n1, int w, int alpha)
{
- alpha = FZ_EXPAND(alpha);
+ if (sa)
+ alpha = FZ_EXPAND(alpha);
while (w--)
{
- int masa = FZ_COMBINE(sp[n-1], alpha);
- int k = n;
+ int masa = (sa ? FZ_COMBINE(sp[n1], alpha) : alpha);
+ int k = n1;
while (k--)
{
*dp = FZ_BLEND(*sp++, *dp, masa);
dp++;
}
+ if (da)
+ {
+ *dp = FZ_BLEND((sa ? *sp : 255), *dp, masa);
+ dp++;
+ }
+ if (sa)
+ sp++;
}
}
/* Blend source over destination */
static inline void
-fz_paint_span_1(byte * restrict dp, byte * restrict sp, int w)
+fz_paint_span_1_dasa(byte * restrict dp, byte * restrict sp, int w)
{
while (w--)
{
@@ -809,14 +1021,14 @@ fz_paint_span_1(byte * restrict dp, byte * restrict sp, int w)
}
static inline void
-fz_paint_span_2(byte * restrict dp, byte * restrict sp, int w)
+fz_paint_span_1(byte * restrict dp, int da, byte * restrict sp, int sa, int w)
{
while (w--)
{
- int t = FZ_EXPAND(sp[1]);
+ int t = (sa ? FZ_EXPAND(sp[1]): 256);
if (t == 0)
{
- dp += 2; sp += 2;
+ dp += 1 + da; sp += 1 + sa;
}
else
{
@@ -824,36 +1036,53 @@ fz_paint_span_2(byte * restrict dp, byte * restrict sp, int w)
if (t == 0)
{
*dp++ = *sp++;
- *dp++ = *sp++;
+ if (da)
+ *dp++ = (sa ? *sp : 255);
+ if (sa)
+ sp++;
}
else
{
*dp = *sp++ + FZ_COMBINE(*dp, t);
dp++;
- *dp = *sp++ + FZ_COMBINE(*dp, t);
- dp++;
+ if (da)
+ {
+ *dp = (sa ? *sp + FZ_COMBINE(*dp, t) : 255);
+ dp++;
+ }
+ if (sa)
+ sp++;
}
}
}
}
static inline void
-fz_paint_span_4(byte * restrict dp, byte * restrict sp, int w)
+fz_paint_span_3(byte * restrict dp, int da, byte * restrict sp, int sa, int w)
{
while (w--)
{
- int t = FZ_EXPAND(sp[3]);
+ int t = (sa ? FZ_EXPAND(sp[3]) : 256);
if (t == 0)
{
- dp += 4; sp += 4;
+ dp += 3 + da; sp += 3 + sa;
}
else
{
t = 256 - t;
if (t == 0)
{
- *(int *)dp = *(int *)sp;
- dp += 4; sp += 4;
+ if (da && sa)
+ *(int *)dp = *(int *)sp;
+ else
+ {
+ dp[0] = sp[0];
+ dp[1] = sp[1];
+ dp[2] = sp[2];
+ if (da)
+ dp[3] = (sa ? sp[3] : 255);
+ }
+ dp += 3+da; sp += 3+sa;
}
else
{
@@ -863,22 +1092,27 @@ fz_paint_span_4(byte * restrict dp, byte * restrict sp, int w)
dp++;
*dp = *sp++ + FZ_COMBINE(*dp, t);
dp++;
- *dp = *sp++ + FZ_COMBINE(*dp, t);
- dp++;
+ if (da)
+ {
+ *dp = (sa ? *sp + FZ_COMBINE(*dp, t) : 255);
+ dp++;
+ }
+ if (sa)
+ sp++;
}
}
}
}
static inline void
-fz_paint_span_5(byte * restrict dp, byte * restrict sp, int w)
+fz_paint_span_4(byte * restrict dp, int da, byte * restrict sp, int sa, int w)
{
while (w--)
{
- int t = FZ_EXPAND(sp[4]);
+ int t = (sa ? FZ_EXPAND(sp[4]) : 256);
if (t == 0)
{
- dp += 5; sp += 5;
+ dp += 4+da; sp += 4+sa;
}
else
{
@@ -889,8 +1123,9 @@ fz_paint_span_5(byte * restrict dp, byte * restrict sp, int w)
dp[1] = sp[1];
dp[2] = sp[2];
dp[3] = sp[3];
- dp[4] = sp[4];
- dp += 5; sp += 5;
+ if (da)
+ dp[4] = (sa ? sp[4] : 255);
+ dp += 4+da; sp += 4 + sa;
}
else
{
@@ -902,69 +1137,163 @@ fz_paint_span_5(byte * restrict dp, byte * restrict sp, int w)
dp++;
*dp = *sp++ + FZ_COMBINE(*dp, t);
dp++;
- *dp = *sp++ + FZ_COMBINE(*dp, t);
- dp++;
+ if (da)
+ {
+ *dp = (sa ? *sp + FZ_COMBINE(*dp, t) : 255);
+ dp++;
+ }
+ if (sa)
+ sp++;
}
}
}
}
static inline void
-fz_paint_span_N(byte * restrict dp, byte * restrict sp, int n, int w)
+fz_paint_span_N(byte * restrict dp, int da, byte * restrict sp, int sa, int n1, int w)
{
while (w--)
{
- int t = FZ_EXPAND(sp[n-1]);
+ int t = (sa ? FZ_EXPAND(sp[n1]) : 256);
if (t == 0)
{
- dp += n; sp += n;
+ dp += n1 + da; sp += n1 + sa;
}
else
{
t = 256 - t;
if (t == 0)
{
- int k = n;
+ int k = n1;
while (k--)
{
*dp++ = *sp++;
}
+ if (da)
+ *dp++ = (sa ? *sp : 255);
+ if (sa)
+ sp++;
}
else
{
- int k = n;
+ int k = n1;
while (k--)
{
*dp = *sp++ + FZ_COMBINE(*dp, t);
dp++;
}
+ if (da)
+ {
+ *dp = (sa ? *sp + FZ_COMBINE(*dp, t) : 255);
+ dp++;
+ }
+ if (sa)
+ sp++;
}
}
}
}
void
-fz_paint_span(byte * restrict dp, byte * restrict sp, int n, int w, int alpha)
+fz_paint_span(byte * restrict dp, int da, byte * restrict sp, int sa, int n, int w, int alpha)
{
- if (alpha == 255)
+ if (da)
{
- switch (n)
+ if (sa)
{
- case 1: fz_paint_span_1(dp, sp, w); break;
- case 2: fz_paint_span_2(dp, sp, w); break;
- case 4: fz_paint_span_4(dp, sp, w); break;
- case 5: fz_paint_span_5(dp, sp, w); break;
- default: fz_paint_span_N(dp, sp, n, w); break;
+ if (alpha == 255)
+ {
+ switch (n)
+ {
+ case 0: fz_paint_span_1_dasa(dp, sp, w); break;
+ case 1: fz_paint_span_1(dp, 1, sp, 1, w); break;
+ case 3: fz_paint_span_3(dp, 1, sp, 1, w); break;
+ case 4: fz_paint_span_4(dp, 1, sp, 1, w); break;
+ default: fz_paint_span_N(dp, 1, sp, 1, n, w); break;
+ }
+ }
+ else if (alpha > 0)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_span_1_with_alpha(dp, 1, sp, 1, w, alpha); break;
+ case 3: fz_paint_span_3_with_alpha(dp, 1, sp, 1, w, alpha); break;
+ case 4: fz_paint_span_4_with_alpha(dp, 1, sp, 1, w, alpha); break;
+ default: fz_paint_span_N_with_alpha(dp, 1, sp, 1, n, w, alpha); break;
+ }
+ }
+ }
+ else
+ {
+ if (alpha == 255)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_span_1(dp, 1, sp, 0, w); break;
+ case 3: fz_paint_span_3(dp, 1, sp, 0, w); break;
+ case 4: fz_paint_span_4(dp, 1, sp, 0, w); break;
+ default: fz_paint_span_N(dp, 1, sp, 0, n, w); break;
+ }
+ }
+ else if (alpha > 0)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_span_1_with_alpha(dp, 1, sp, 0, w, alpha); break;
+ case 3: fz_paint_span_3_with_alpha(dp, 1, sp, 0, w, alpha); break;
+ case 4: fz_paint_span_4_with_alpha(dp, 1, sp, 0, w, alpha); break;
+ default: fz_paint_span_N_with_alpha(dp, 1, sp, 0, n, w, alpha); break;
+ }
+ }
}
}
- else if (alpha > 0)
+ else
{
- switch (n)
+ if (sa)
+ {
+ if (alpha == 255)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_span_1(dp, 0, sp, 1, w); break;
+ case 3: fz_paint_span_3(dp, 0, sp, 1, w); break;
+ case 4: fz_paint_span_4(dp, 0, sp, 1, w); break;
+ default: fz_paint_span_N(dp, 0, sp, 1, n, w); break;
+ }
+ }
+ else if (alpha > 0)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_span_1_with_alpha(dp, 0, sp, 1, w, alpha); break;
+ case 3: fz_paint_span_3_with_alpha(dp, 0, sp, 1, w, alpha); break;
+ case 4: fz_paint_span_4_with_alpha(dp, 0, sp, 1, w, alpha); break;
+ default: fz_paint_span_N_with_alpha(dp, 0, sp, 1, n, w, alpha); break;
+ }
+ }
+ }
+ else
{
- case 2: fz_paint_span_2_with_alpha(dp, sp, w, alpha); break;
- case 4: fz_paint_span_4_with_alpha(dp, sp, w, alpha); break;
- case 5: fz_paint_span_5_with_alpha(dp, sp, w, alpha); break;
- default: fz_paint_span_N_with_alpha(dp, sp, n, w, alpha); break;
+ if (alpha == 255)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_span_1(dp, 0, sp, 0, w); break;
+ case 3: fz_paint_span_3(dp, 0, sp, 0, w); break;
+ case 4: fz_paint_span_4(dp, 0, sp, 0, w); break;
+ default: fz_paint_span_N(dp, 0, sp, 0, n, w); break;
+ }
+ }
+ else if (alpha > 0)
+ {
+ switch (n)
+ {
+ case 1: fz_paint_span_1_with_alpha(dp, 0, sp, 0, w, alpha); break;
+ case 3: fz_paint_span_3_with_alpha(dp, 0, sp, 0, w, alpha); break;
+ case 4: fz_paint_span_4_with_alpha(dp, 0, sp, 0, w, alpha); break;
+ default: fz_paint_span_N_with_alpha(dp, 0 ,sp, 0, n, w, alpha); break;
+ }
+ }
}
}
}
@@ -977,10 +1306,10 @@ void
fz_paint_pixmap_with_bbox(fz_pixmap *dst, fz_pixmap *src, int alpha, fz_irect bbox)
{
unsigned char *sp, *dp;
- int x, y, w, h, n;
+ int x, y, w, h, n, da, sa;
fz_irect bbox2;
- assert(dst->n == src->n);
+ assert(dst->n - dst->alpha == src->n - src->alpha);
fz_pixmap_bbox_no_ctx(dst, &bbox2);
fz_intersect_irect(&bbox, &bbox2);
@@ -995,14 +1324,17 @@ fz_paint_pixmap_with_bbox(fz_pixmap *dst, fz_pixmap *src, int alpha, fz_irect bb
return;
n = src->n;
- sp = src->samples + (unsigned int)(((y - src->y) * src->w + (x - src->x)) * src->n);
- dp = dst->samples + (unsigned int)(((y - dst->y) * dst->w + (x - dst->x)) * dst->n);
+ sp = src->samples + (unsigned int)((y - src->y) * src->stride + (x - src->x) * src->n);
+ sa = src->alpha;
+ dp = dst->samples + (unsigned int)((y - dst->y) * dst->stride + (x - dst->x) * dst->n);
+ da = dst->alpha;
+ n -= sa;
while (h--)
{
- fz_paint_span(dp, sp, n, w, alpha);
- sp += src->w * n;
- dp += dst->w * n;
+ fz_paint_span(dp, da, sp, sa, n, w, alpha);
+ sp += src->stride;
+ dp += dst->stride;
}
}
@@ -1012,9 +1344,9 @@ fz_paint_pixmap(fz_pixmap *dst, fz_pixmap *src, int alpha)
unsigned char *sp, *dp;
fz_irect bbox;
fz_irect bbox2;
- int x, y, w, h, n;
+ int x, y, w, h, n, da, sa;
- assert(dst->n == src->n);
+ assert(dst->n - dst->alpha == src->n - src->alpha);
fz_pixmap_bbox_no_ctx(dst, &bbox);
fz_pixmap_bbox_no_ctx(src, &bbox2);
@@ -1028,14 +1360,17 @@ fz_paint_pixmap(fz_pixmap *dst, fz_pixmap *src, int alpha)
return;
n = src->n;
- sp = src->samples + (unsigned int)(((y - src->y) * src->w + (x - src->x)) * src->n);
- dp = dst->samples + (unsigned int)(((y - dst->y) * dst->w + (x - dst->x)) * dst->n);
+ sp = src->samples + (unsigned int)((y - src->y) * src->stride + (x - src->x) * src->n);
+ sa = src->alpha;
+ dp = dst->samples + (unsigned int)((y - dst->y) * dst->stride + (x - dst->x) * dst->n);
+ da = dst->alpha;
+ n -= sa;
while (h--)
{
- fz_paint_span(dp, sp, n, w, alpha);
- sp += src->w * n;
- dp += dst->w * n;
+ fz_paint_span(dp, da, sp, sa, n, w, alpha);
+ sp += src->stride;
+ dp += dst->stride;
}
}
@@ -1044,7 +1379,7 @@ fz_paint_pixmap_with_mask(fz_pixmap *dst, fz_pixmap *src, fz_pixmap *msk)
{
unsigned char *sp, *dp, *mp;
fz_irect bbox, bbox2;
- int x, y, w, h, n;
+ int x, y, w, h, n, sa, da;
assert(dst->n == src->n);
assert(msk->n == 1);
@@ -1063,21 +1398,24 @@ fz_paint_pixmap_with_mask(fz_pixmap *dst, fz_pixmap *src, fz_pixmap *msk)
return;
n = src->n;
- sp = src->samples + (unsigned int)(((y - src->y) * src->w + (x - src->x)) * src->n);
- mp = msk->samples + (unsigned int)(((y - msk->y) * msk->w + (x - msk->x)) * msk->n);
- dp = dst->samples + (unsigned int)(((y - dst->y) * dst->w + (x - dst->x)) * dst->n);
+ sp = src->samples + (unsigned int)((y - src->y) * src->stride + (x - src->x) * src->n);
+ sa = src->alpha;
+ mp = msk->samples + (unsigned int)((y - msk->y) * msk->stride + (x - msk->x) * msk->n);
+ dp = dst->samples + (unsigned int)((y - dst->y) * dst->stride + (x - dst->x) * dst->n);
+ da = dst->alpha;
+ n -= sa;
while (h--)
{
- fz_paint_span_with_mask(dp, sp, mp, n, w);
- sp += src->w * n;
- dp += dst->w * n;
- mp += msk->w;
+ fz_paint_span_with_mask(dp, da, sp, sa, mp, n, w);
+ sp += src->stride;
+ dp += dst->stride;
+ mp += msk->stride;
}
}
static inline void
-fz_paint_glyph_mask(int span, unsigned char *dp, fz_glyph *glyph, int w, int h, int skip_x, int skip_y)
+fz_paint_glyph_mask(int span, unsigned char *dp, int da, fz_glyph *glyph, int w, int h, int skip_x, int skip_y)
{
while (h--)
{
@@ -1205,82 +1543,163 @@ intermediate_run:
}
}
-#define N 2
+#define DA
+#define N 1
#include "paint-glyph.h"
+#define DA
+#define N 3
+#include "paint-glyph.h"
+
+#define DA
#define N 4
#include "paint-glyph.h"
-#define N 5
+#define DA
#include "paint-glyph.h"
+#define DA
+#define ALPHA
+#define N 1
#include "paint-glyph.h"
+#define DA
#define ALPHA
-#define N 2
+#define N 3
#include "paint-glyph.h"
+#define DA
#define ALPHA
#define N 4
#include "paint-glyph.h"
+#define DA
#define ALPHA
-#define N 5
+#include "paint-glyph.h"
+
+#define N 1
+#include "paint-glyph.h"
+
+#define N 3
+#include "paint-glyph.h"
+
+#define N 4
+#include "paint-glyph.h"
+
+#include "paint-glyph.h"
+
+#define ALPHA
+#define N 1
+#include "paint-glyph.h"
+
+#define ALPHA
+#define N 3
+#include "paint-glyph.h"
+
+#define ALPHA
+#define N 4
#include "paint-glyph.h"
#define ALPHA
#include "paint-glyph.h"
static inline void
-fz_paint_glyph_alpha(unsigned char *colorbv, int n, int span, unsigned char *dp, fz_glyph *glyph, int w, int h, int skip_x, int skip_y)
+fz_paint_glyph_alpha(unsigned char *colorbv, int n, int span, unsigned char *dp, int da, fz_glyph *glyph, int w, int h, int skip_x, int skip_y)
{
- switch (n)
+ if (da)
{
- case 2:
- fz_paint_glyph_alpha_2(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
- break;
- case 4:
- fz_paint_glyph_alpha_4(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
- break;
- case 5:
- fz_paint_glyph_alpha_5(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
- break;
- default:
- fz_paint_glyph_alpha_N(colorbv, n, span, dp, glyph, w, h, skip_x, skip_y);
- break;
+ switch (n)
+ {
+ case 1:
+ fz_paint_glyph_alpha_1_da(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
+ break;
+ case 3:
+ fz_paint_glyph_alpha_3_da(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
+ break;
+ case 4:
+ fz_paint_glyph_alpha_4_da(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
+ break;
+ default:
+ fz_paint_glyph_alpha_N_da(colorbv, n, span, dp, glyph, w, h, skip_x, skip_y);
+ break;
+ }
+ }
+ else
+ {
+ switch (n)
+ {
+ case 1:
+ fz_paint_glyph_alpha_1(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
+ break;
+ case 3:
+ fz_paint_glyph_alpha_3(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
+ break;
+ case 4:
+ fz_paint_glyph_alpha_4(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
+ break;
+ default:
+ fz_paint_glyph_alpha_N(colorbv, n, span, dp, glyph, w, h, skip_x, skip_y);
+ break;
+ }
}
}
static inline void
-fz_paint_glyph_solid(unsigned char *colorbv, int n, int span, unsigned char *dp, fz_glyph *glyph, int w, int h, int skip_x, int skip_y)
+fz_paint_glyph_solid(unsigned char *colorbv, int n, int span, unsigned char *dp, int da, fz_glyph *glyph, int w, int h, int skip_x, int skip_y)
{
- switch (n)
+ if (da)
{
- case 2:
- fz_paint_glyph_solid_2(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
- break;
- case 4:
- fz_paint_glyph_solid_4(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
- break;
- case 5:
- fz_paint_glyph_solid_5(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
- break;
- default:
- fz_paint_glyph_solid_N(colorbv, n, span, dp, glyph, w, h, skip_x, skip_y);
- break;
+ switch (n)
+ {
+ case 1:
+ fz_paint_glyph_solid_1_da(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
+ break;
+ case 3:
+ fz_paint_glyph_solid_3_da(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
+ break;
+ case 4:
+ fz_paint_glyph_solid_4_da(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
+ break;
+ default:
+ fz_paint_glyph_solid_N_da(colorbv, n, span, dp, glyph, w, h, skip_x, skip_y);
+ break;
+ }
+ }
+ else
+ {
+ switch (n)
+ {
+ case 1:
+ fz_paint_glyph_solid_1(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
+ break;
+ case 3:
+ fz_paint_glyph_solid_3(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
+ break;
+ case 4:
+ fz_paint_glyph_solid_4(colorbv, span, dp, glyph, w, h, skip_x, skip_y);
+ break;
+ default:
+ fz_paint_glyph_solid_N(colorbv, n, span, dp, glyph, w, h, skip_x, skip_y);
+ break;
+ }
}
}
void
fz_paint_glyph(unsigned char *colorbv, fz_pixmap *dst, unsigned char *dp, fz_glyph *glyph, int w, int h, int skip_x, int skip_y)
{
+ int n = dst->n - dst->alpha;
if (dst->colorspace)
{
- if (colorbv[dst->n-1] == 255)
- fz_paint_glyph_solid(colorbv, dst->n, dst->w * dst->n, dp, glyph, w, h, skip_x, skip_y);
- else if (colorbv[dst->n-1] != 0)
- fz_paint_glyph_alpha(colorbv, dst->n, dst->w * dst->n, dp, glyph, w, h, skip_x, skip_y);
+ assert(n > 0);
+ if (colorbv[n] == 255)
+ fz_paint_glyph_solid(colorbv, n, dst->stride, dp, dst->alpha, glyph, w, h, skip_x, skip_y);
+ else if (colorbv[n] != 0)
+ fz_paint_glyph_alpha(colorbv, n, dst->stride, dp, dst->alpha, glyph, w, h, skip_x, skip_y);
}
else
- fz_paint_glyph_mask(dst->w, dp, glyph, w, h, skip_x, skip_y);
+ {
+ assert(dst->alpha && dst->n == 1 && dst->colorspace == NULL);
+ fz_paint_glyph_mask(dst->stride, dp, dst->alpha, glyph, w, h, skip_x, skip_y);
+ }
}
diff --git a/source/fitz/draw-scale-simple.c b/source/fitz/draw-scale-simple.c
index cf9251e7..0f267743 100644
--- a/source/fitz/draw-scale-simple.c
+++ b/source/fitz/draw-scale-simple.c
@@ -1027,21 +1027,29 @@ scale_row_from_temp(unsigned char *dst, unsigned char *src, fz_weights *weights,
#ifdef SINGLE_PIXEL_SPECIALS
static void
-duplicate_single_pixel(unsigned char *dst, unsigned char *src, int n, int w, int h)
+duplicate_single_pixel(unsigned char *dst, unsigned char *src, int n, int w, int h, int stride)
{
int i;
+ w *= n;
for (i = n; i > 0; i--)
*dst++ = *src++;
- for (i = (w*h-1)*n; i > 0; i--)
+ for (i = w-n; i > 0; i--)
{
*dst = dst[-n];
dst++;
}
+ dst -= w;
+ h--;
+ while (h--)
+ {
+ memcpy(dst+stride, dst, w);
+ dst += stride;
+ }
}
static void
-scale_single_row(unsigned char *dst, unsigned char *src, fz_weights *weights, int src_w, int h)
+scale_single_row(unsigned char *dst, int dstride, unsigned char *src, fz_weights *weights, int src_w, int h)
{
int *contrib = &weights->index[weights->index[0]];
int min, len, i, j, n;
@@ -1072,7 +1080,7 @@ scale_single_row(unsigned char *dst, unsigned char *src, fz_weights *weights, in
}
dst -= 2*n;
}
- dst += n * (weights->count+1);
+ dst += n + dstride;
}
else
{
@@ -1093,18 +1101,19 @@ scale_single_row(unsigned char *dst, unsigned char *src, fz_weights *weights, in
tmp[j] = 128;
}
}
+ dst += dstride - weights->count * n;
}
/* And then duplicate it h times */
n *= weights->count;
while (--h > 0)
{
- memcpy(dst, dst-n, n);
- dst += n;
+ memcpy(dst, dst-dstride, n);
+ dst += dstride;
}
}
static void
-scale_single_col(unsigned char *dst, unsigned char *src, fz_weights *weights, int src_w, int n, int w, int flip_y)
+scale_single_col(unsigned char *dst, int dstride, unsigned char *src, int sstride, fz_weights *weights, int src_w, int n, int w, int flip_y)
{
int *contrib = &weights->index[weights->index[0]];
int min, len, i, j;
@@ -1114,18 +1123,18 @@ scale_single_col(unsigned char *dst, unsigned char *src, fz_weights *weights, in
tmp[j] = 128;
if (flip_y)
{
- src_w = (src_w-1)*n;
- w = (w-1)*n;
+ src_w = (src_w-1)*sstride;
for (i=weights->count; i > 0; i--)
{
/* Scale the next pixel in the column */
min = *contrib++;
len = *contrib++;
- min = src_w-min*n;
+ min = src_w-min*sstride;
while (len-- > 0)
{
for (j = 0; j < n; j++)
- tmp[j] += src[src_w-min+j] * *contrib;
+ tmp[j] += src[min+j] * *contrib;
+ min -= sstride;
contrib++;
}
for (j = 0; j < n; j++)
@@ -1134,26 +1143,27 @@ scale_single_col(unsigned char *dst, unsigned char *src, fz_weights *weights, in
tmp[j] = 128;
}
/* And then duplicate it across the row */
- for (j = w; j > 0; j--)
+ for (j = (w-1)*n; j > 0; j--)
{
*dst = dst[-n];
dst++;
}
+ dst += dstride - w*n;
}
}
else
{
- w = (w-1)*n;
for (i=weights->count; i > 0; i--)
{
/* Scale the next pixel in the column */
min = *contrib++;
len = *contrib++;
- min *= n;
+ min *= sstride;
while (len-- > 0)
{
for (j = 0; j < n; j++)
- tmp[j] += src[min++] * *contrib;
+ tmp[j] += src[min+j] * *contrib;
+ min += sstride;
contrib++;
}
for (j = 0; j < n; j++)
@@ -1162,11 +1172,12 @@ scale_single_col(unsigned char *dst, unsigned char *src, fz_weights *weights, in
tmp[j] = 128;
}
/* And then duplicate it across the row */
- for (j = w; j > 0; j--)
+ for (j = (w-1)*n; j > 0; j--)
{
*dst = dst[-n];
dst++;
}
+ dst += dstride - w*n;
}
}
}
@@ -1284,6 +1295,8 @@ fz_scale_pixmap_cached(fz_context *ctx, const fz_pixmap *src, float x, float y,
dst_h_int = (int)ceilf(y + h);
}
+ fz_valgrind_pixmap(src);
+
/* Step 0: Calculate the patch */
patch.x0 = 0;
patch.y0 = 0;
@@ -1352,7 +1365,7 @@ fz_scale_pixmap_cached(fz_context *ctx, const fz_pixmap *src, float x, float y,
#endif /* SINGLE_PIXEL_SPECIALS */
contrib_rows = make_weights(ctx, src->h, y, h, filter, 1, dst_h_int, patch.y0, patch.y1, src->n, flip_y, cache_y);
- output = fz_new_pixmap(ctx, src->colorspace, patch.x1 - patch.x0, patch.y1 - patch.y0);
+ output = fz_new_pixmap(ctx, src->colorspace, patch.x1 - patch.x0, patch.y1 - patch.y0, src->alpha);
}
fz_catch(ctx)
{
@@ -1373,18 +1386,21 @@ fz_scale_pixmap_cached(fz_context *ctx, const fz_pixmap *src, float x, float y,
if (!contrib_cols)
{
/* Only 1 pixel in the entire image! */
- duplicate_single_pixel(output->samples, src->samples, src->n, patch.x1-patch.x0, patch.y1-patch.y0);
+ duplicate_single_pixel(output->samples, src->samples, src->n, patch.x1-patch.x0, patch.y1-patch.y0, output->stride);
+ fz_valgrind_pixmap(output);
}
else
{
/* Scale the row once, then copy it. */
- scale_single_row(output->samples, src->samples, contrib_cols, src->w, patch.y1-patch.y0);
+ scale_single_row(output->samples, output->stride, src->samples, contrib_cols, src->w, patch.y1-patch.y0);
+ fz_valgrind_pixmap(output);
}
}
else if (!contrib_cols)
{
/* Only 1 source pixel wide. Scale the col and duplicate. */
- scale_single_col(output->samples, src->samples, contrib_rows, src->h, src->n, patch.x1-patch.x0, flip_y);
+ scale_single_col(output->samples, output->stride, src->samples, src->stride, contrib_rows, src->h, src->n, patch.x1-patch.x0, flip_y);
+ fz_valgrind_pixmap(output);
}
else
#endif /* SINGLE_PIXEL_SPECIALS */
@@ -1438,13 +1454,15 @@ fz_scale_pixmap_cached(fz_context *ctx, const fz_pixmap *src, float x, float y,
{
/* Scale another row */
assert(max_row < src->h);
- (*row_scale)(&temp[temp_span*(max_row % temp_rows)], &src->samples[(flip_y ? (src->h-1-max_row): max_row)*src->w*src->n], contrib_cols);
+ (*row_scale)(&temp[temp_span*(max_row % temp_rows)], &src->samples[(flip_y ? (src->h-1-max_row): max_row)*src->stride], contrib_cols);
max_row++;
}
- scale_row_from_temp(&output->samples[row*output->w*output->n], temp, contrib_rows, temp_span, row);
+ scale_row_from_temp(&output->samples[row*output->stride], temp, contrib_rows, temp_span, row);
}
fz_free(ctx, temp);
+
+ fz_valgrind_pixmap(output);
}
cleanup:
@@ -1452,6 +1470,7 @@ cleanup:
fz_free(ctx, contrib_rows);
if (!cache_x)
fz_free(ctx, contrib_cols);
+
return output;
}
diff --git a/source/fitz/draw-unpack.c b/source/fitz/draw-unpack.c
index d21e7303..8ac76bdc 100644
--- a/source/fitz/draw-unpack.c
+++ b/source/fitz/draw-unpack.c
@@ -72,7 +72,7 @@ fz_unpack_tile(fz_context *ctx, fz_pixmap *dst, unsigned char * restrict src, in
for (y = 0; y < dst->h; y++)
{
unsigned char *sp = src + (unsigned int)(y * stride);
- unsigned char *dp = dst->samples + (unsigned int)(y * dst->w * dst->n);
+ unsigned char *dp = dst->samples + (unsigned int)(y * dst->stride);
/* Specialized loops */
@@ -177,10 +177,12 @@ fz_decode_indexed_tile(fz_context *ctx, fz_pixmap *pix, const float *decode, int
int add[FZ_MAX_COLORS];
int mul[FZ_MAX_COLORS];
unsigned char *p = pix->samples;
- int len = pix->w * pix->h;
+ int stride = pix->stride - pix->w * pix->n;
+ int len;
int n = pix->n - 1;
int needed;
int k;
+ int h;
needed = 0;
for (k = 0; k < n; k++)
@@ -195,14 +197,20 @@ fz_decode_indexed_tile(fz_context *ctx, fz_pixmap *pix, const float *decode, int
if (!needed)
return;
- while (len--)
+ h = pix->h;
+ while (h--)
{
- for (k = 0; k < n; k++)
+ len = pix->w;
+ while (len--)
{
- int value = (add[k] + (((p[k] << 8) * mul[k]) >> 8)) >> 8;
- p[k] = fz_clampi(value, 0, 255);
+ for (k = 0; k < n; k++)
+ {
+ int value = (add[k] + (((p[k] << 8) * mul[k]) >> 8)) >> 8;
+ p[k] = fz_clampi(value, 0, 255);
+ }
+ p += n + 1;
}
- p += n + 1;
+ p += stride;
}
}
@@ -212,10 +220,12 @@ fz_decode_tile(fz_context *ctx, fz_pixmap *pix, const float *decode)
int add[FZ_MAX_COLORS];
int mul[FZ_MAX_COLORS];
unsigned char *p = pix->samples;
- int len = pix->w * pix->h;
+ int stride = pix->stride - pix->w * pix->n;
+ int len;
int n = fz_maxi(1, pix->n - 1);
int needed;
int k;
+ int h;
needed = 0;
for (k = 0; k < n; k++)
@@ -230,13 +240,19 @@ fz_decode_tile(fz_context *ctx, fz_pixmap *pix, const float *decode)
if (!needed)
return;
- while (len--)
+ h = pix->h;
+ while (h--)
{
- for (k = 0; k < n; k++)
+ len = pix->w;
+ while (len--)
{
- int value = add[k] + fz_mul255(p[k], mul[k]);
- p[k] = fz_clampi(value, 0, 255);
+ for (k = 0; k < n; k++)
+ {
+ int value = add[k] + fz_mul255(p[k], mul[k]);
+ p[k] = fz_clampi(value, 0, 255);
+ }
+ p += pix->n;
}
- p += pix->n;
+ p += stride;
}
}
diff --git a/source/fitz/font.c b/source/fitz/font.c
index e67f64dc..07476235 100644
--- a/source/fitz/font.c
+++ b/source/fitz/font.c
@@ -1241,7 +1241,8 @@ fz_render_t3_glyph_pixmap(fz_context *ctx, fz_font *font, int gid, const fz_matr
fz_irect_from_rect(&bbox, &bounds);
fz_intersect_irect(&bbox, scissor);
- glyph = fz_new_pixmap_with_bbox(ctx, model ? model : fz_device_gray(ctx), &bbox);
+ /* Glyphs must always have alpha */
+ glyph = fz_new_pixmap_with_bbox(ctx, model, &bbox, 1);
fz_clear_pixmap(ctx, glyph);
dev = fz_new_draw_device_type3(ctx, glyph);
diff --git a/source/fitz/glyph.c b/source/fitz/glyph.c
index 180b7421..b76d2f76 100644
--- a/source/fitz/glyph.c
+++ b/source/fitz/glyph.c
@@ -145,7 +145,7 @@ fz_new_glyph_from_pixmap(fz_context *ctx, fz_pixmap *pix)
glyph->pixmap = fz_keep_pixmap(ctx, pix);
}
else
- glyph = fz_new_glyph_from_8bpp_data(ctx, pix->x, pix->y, pix->w, pix->h, pix->samples, pix->w);
+ glyph = fz_new_glyph_from_8bpp_data(ctx, pix->x, pix->y, pix->w, pix->h, pix->samples, pix->stride);
}
fz_always(ctx)
{
diff --git a/source/fitz/halftone.c b/source/fitz/halftone.c
index 707084c4..60e3c182 100644
--- a/source/fitz/halftone.c
+++ b/source/fitz/halftone.c
@@ -68,7 +68,7 @@ fz_halftone *fz_default_halftone(fz_context *ctx, int num_comps)
{
int i;
for (i = 0; i < num_comps; i++)
- ht->comp[i] = fz_new_pixmap_with_data(ctx, NULL, 16, 16, mono_ht);
+ ht->comp[i] = fz_new_pixmap_with_data(ctx, NULL, 16, 16, 1, 16, mono_ht);
}
fz_catch(ctx)
{
@@ -285,21 +285,21 @@ static void do_threshold_1(const unsigned char * restrict ht_line, const unsigne
h = 0;
if (pixmap[0] < ht_line[0])
h |= 0x80;
- if (pixmap[2] < ht_line[1])
+ if (pixmap[1] < ht_line[1])
h |= 0x40;
- if (pixmap[4] < ht_line[2])
+ if (pixmap[2] < ht_line[2])
h |= 0x20;
- if (pixmap[6] < ht_line[3])
+ if (pixmap[3] < ht_line[3])
h |= 0x10;
- if (pixmap[8] < ht_line[4])
+ if (pixmap[4] < ht_line[4])
h |= 0x08;
- if (pixmap[10] < ht_line[5])
+ if (pixmap[5] < ht_line[5])
h |= 0x04;
- if (pixmap[12] < ht_line[6])
+ if (pixmap[6] < ht_line[6])
h |= 0x02;
- if (pixmap[14] < ht_line[7])
+ if (pixmap[7] < ht_line[7])
h |= 0x01;
- pixmap += 16; /* Skip the alpha */
+ pixmap += 8;
ht_line += 8;
l -= 8;
if (l == 0)
@@ -315,17 +315,17 @@ static void do_threshold_1(const unsigned char * restrict ht_line, const unsigne
h = 0;
if (pixmap[0] < ht_line[0])
h |= 0x80;
- if (w > -6 && pixmap[2] < ht_line[1])
+ if (w > -6 && pixmap[1] < ht_line[1])
h |= 0x40;
- if (w > -5 && pixmap[4] < ht_line[2])
+ if (w > -5 && pixmap[2] < ht_line[2])
h |= 0x20;
- if (w > -4 && pixmap[6] < ht_line[3])
+ if (w > -4 && pixmap[3] < ht_line[3])
h |= 0x10;
- if (w > -3 && pixmap[8] < ht_line[4])
+ if (w > -3 && pixmap[4] < ht_line[4])
h |= 0x08;
- if (w > -2 && pixmap[10] < ht_line[5])
+ if (w > -2 && pixmap[5] < ht_line[5])
h |= 0x04;
- if (w > -1 && pixmap[12] < ht_line[6])
+ if (w > -1 && pixmap[6] < ht_line[6])
h |= 0x02;
*out++ = h;
}
@@ -541,13 +541,13 @@ static void do_threshold_4(const unsigned char * restrict ht_line, const unsigne
h |= 0x20;
if (pixmap[3] >= ht_line[3])
h |= 0x10;
- if (pixmap[5] >= ht_line[4])
+ if (pixmap[4] >= ht_line[4])
h |= 0x08;
- if (pixmap[6] >= ht_line[5])
+ if (pixmap[5] >= ht_line[5])
h |= 0x04;
- if (pixmap[7] >= ht_line[6])
+ if (pixmap[6] >= ht_line[6])
h |= 0x02;
- if (pixmap[8] >= ht_line[7])
+ if (pixmap[7] >= ht_line[7])
h |= 0x01;
*out++ = h;
l -= 2;
@@ -556,7 +556,7 @@ static void do_threshold_4(const unsigned char * restrict ht_line, const unsigne
l = ht_len;
ht_line -= ht_len<<2;
}
- pixmap += 10;
+ pixmap += 8;
ht_line += 8;
w -= 2;
}
@@ -609,11 +609,13 @@ fz_bitmap *fz_new_bitmap_from_pixmap_band(fz_context *ctx, fz_pixmap *pix, fz_ha
if (!pix)
return NULL;
+ assert(pix->alpha == 0);
+
fz_var(ht_line);
fz_var(out);
band *= bandheight;
- n = pix->n-1; /* Remove alpha */
+ n = pix->n;
switch(n)
{
@@ -659,7 +661,7 @@ fz_bitmap *fz_new_bitmap_from_pixmap_band(fz_context *ctx, fz_pixmap *pix, fz_ha
y = pix->y + band;
w = pix->w;
ostride = out->stride;
- pstride = pix->w * pix->n;
+ pstride = pix->stride;
while (h--)
{
make_ht_line(ht_line, ht, x, y++, lcm);
diff --git a/source/fitz/image.c b/source/fitz/image.c
index d8fcdc20..bd6e0b62 100644
--- a/source/fitz/image.c
+++ b/source/fitz/image.c
@@ -95,18 +95,25 @@ static void
fz_mask_color_key(fz_pixmap *pix, int n, const int *colorkey)
{
unsigned char *p = pix->samples;
- int len = pix->w * pix->h;
+ int w;
int k, t;
- while (len--)
+ int h = pix->h;
+ int stride = pix->stride - pix->w * pix->n;
+ while (h--)
{
- t = 1;
- for (k = 0; k < n; k++)
- if (p[k] < colorkey[k * 2] || p[k] > colorkey[k * 2 + 1])
- t = 0;
- if (t)
- for (k = 0; k < pix->n; k++)
- p[k] = 0;
- p += pix->n;
+ w = pix->w;
+ while (w--)
+ {
+ t = 1;
+ for (k = 0; k < n; k++)
+ if (p[k] < colorkey[k * 2] || p[k] > colorkey[k * 2 + 1])
+ t = 0;
+ if (t)
+ for (k = 0; k < pix->n; k++)
+ p[k] = 0;
+ p += pix->n;
+ }
+ p += stride;
}
}
@@ -114,9 +121,13 @@ static void
fz_unblend_masked_tile(fz_context *ctx, fz_pixmap *tile, fz_image *image)
{
fz_pixmap *mask = fz_get_pixmap_from_image(ctx, image->mask, NULL, NULL, NULL, NULL);
- unsigned char *s = mask->samples, *end = s + mask->w * mask->h;
+ unsigned char *s = mask->samples;
unsigned char *d = tile->samples;
+ int n = tile->n;
int k;
+ int sstride = mask->stride - mask->w * mask->n;
+ int dstride = tile->stride - tile->w * tile->n;
+ int h = mask->h;
if (tile->w != mask->w || tile->h != mask->h)
{
@@ -125,14 +136,22 @@ fz_unblend_masked_tile(fz_context *ctx, fz_pixmap *tile, fz_image *image)
return;
}
- for (; s < end; s++, d += tile->n)
+ while (h--)
{
- if (*s == 0)
- for (k = 0; k < image->n; k++)
- d[k] = image->colorkey[k];
- else
- for (k = 0; k < image->n; k++)
- d[k] = fz_clampi(image->colorkey[k] + (d[k] - image->colorkey[k]) * 255 / *s, 0, 255);
+ int w = mask->w;
+ while (w--)
+ {
+ if (*s == 0)
+ for (k = 0; k < image->n; k++)
+ d[k] = image->colorkey[k];
+ else
+ for (k = 0; k < image->n; k++)
+ d[k] = fz_clampi(image->colorkey[k] + (d[k] - image->colorkey[k]) * 255 / *s, 0, 255);
+ s++;
+ d += n;
+ }
+ s += sstride;
+ d += dstride;
}
fz_drop_pixmap(ctx, mask);
@@ -179,7 +198,7 @@ fz_decomp_image_from_stream(fz_context *ctx, fz_stream *stm, fz_compressed_image
fz_try(ctx)
{
- tile = fz_new_pixmap(ctx, image->colorspace, w, h);
+ tile = fz_new_pixmap(ctx, image->colorspace, w, h, 1);
tile->interpolate = image->interpolate;
stride = (w * image->n * image->bpc + 7) / 8;
@@ -982,13 +1001,13 @@ display_list_image_get_pixmap(fz_context *ctx, fz_image *image_, fz_irect *subar
int r = (subarea->x1 * w + image->super.w - 1) / image->super.w;
int b = (subarea->y1 * h + image->super.h - 1) / image->super.h;
- pix = fz_new_pixmap(ctx, image->super.colorspace, r-l, b-t);
+ pix = fz_new_pixmap(ctx, image->super.colorspace, r-l, b-t, 0);
pix->x = l;
pix->y = t;
}
else
{
- pix = fz_new_pixmap(ctx, image->super.colorspace, w, h);
+ pix = fz_new_pixmap(ctx, image->super.colorspace, w, h, 0);
}
/* If we render the displaylist into pix with the image matrix, we'll get a unit
diff --git a/source/fitz/load-bmp.c b/source/fitz/load-bmp.c
index 433b9dd1..a15ec093 100644
--- a/source/fitz/load-bmp.c
+++ b/source/fitz/load-bmp.c
@@ -697,7 +697,7 @@ bmp_read_bitmap(fz_context *ctx, struct info *info, unsigned char *p, unsigned c
}
fz_try(ctx)
- pix = fz_new_pixmap(ctx, fz_device_rgb(ctx), width, height);
+ pix = fz_new_pixmap(ctx, fz_device_rgb(ctx), width, height, 1);
fz_catch(ctx)
{
fz_free(ctx, decompressed);
@@ -705,7 +705,7 @@ bmp_read_bitmap(fz_context *ctx, struct info *info, unsigned char *p, unsigned c
}
ddp = pix->samples;
- dstride = width * 4;
+ dstride = pix->stride;
if (!info->topdown)
{
ddp = pix->samples + (height - 1) * dstride;
diff --git a/source/fitz/load-gif.c b/source/fitz/load-gif.c
index 02c153f0..d31dee09 100644
--- a/source/fitz/load-gif.c
+++ b/source/fitz/load-gif.c
@@ -401,7 +401,7 @@ gif_read_image(fz_context *ctx, struct info *info, unsigned char *p, int total,
if (only_metadata)
return NULL;
- pix = fz_new_pixmap(ctx, fz_device_rgb(ctx), info->width, info->height);
+ pix = fz_new_pixmap(ctx, fz_device_rgb(ctx), info->width, info->height, 1);
fz_try(ctx)
{
diff --git a/source/fitz/load-jpeg.c b/source/fitz/load-jpeg.c
index 29db9bcf..6aac519c 100644
--- a/source/fitz/load-jpeg.c
+++ b/source/fitz/load-jpeg.c
@@ -223,7 +223,7 @@ fz_load_jpeg(fz_context *ctx, unsigned char *rbuf, int rlen)
unsigned char *row[1], *sp, *dp;
fz_colorspace *colorspace;
unsigned int x;
- int k;
+ int k, stride;
fz_pixmap *image = NULL;
fz_var(image);
@@ -266,7 +266,7 @@ fz_load_jpeg(fz_context *ctx, unsigned char *rbuf, int rlen)
else
fz_throw(ctx, FZ_ERROR_GENERIC, "bad number of components in jpeg: %d", cinfo.num_components);
- image = fz_new_pixmap(ctx, colorspace, cinfo.output_width, cinfo.output_height);
+ image = fz_new_pixmap(ctx, colorspace, cinfo.output_width, cinfo.output_height, 1);
if (extract_exif_resolution(cinfo.marker_list, &image->xres, &image->yres))
/* XPS prefers EXIF resolution to JFIF density */;
@@ -290,6 +290,7 @@ fz_load_jpeg(fz_context *ctx, unsigned char *rbuf, int rlen)
row[0] = fz_malloc(ctx, cinfo.output_components * cinfo.output_width);
dp = image->samples;
+ stride = image->stride - image->w * image->n;
while (cinfo.output_scanline < cinfo.output_height)
{
jpeg_read_scanlines(&cinfo, row, 1);
@@ -300,6 +301,7 @@ fz_load_jpeg(fz_context *ctx, unsigned char *rbuf, int rlen)
*dp++ = *sp++;
*dp++ = 255;
}
+ dp += stride;
}
}
fz_always(ctx)
diff --git a/source/fitz/load-jpx.c b/source/fitz/load-jpx.c
index 3ea7775c..6a8c36c0 100644
--- a/source/fitz/load-jpx.c
+++ b/source/fitz/load-jpx.c
@@ -83,7 +83,7 @@ fz_load_jpx(fz_context *ctx, unsigned char *data, int size, fz_colorspace *defcs
unsigned char *p;
OPJ_CODEC_FORMAT format;
int a, n, w, h, depth, sgnd;
- int x, y, k, v;
+ int x, y, k, v, stride;
stream_block sb;
if (size < 2)
@@ -204,7 +204,7 @@ fz_load_jpx(fz_context *ctx, unsigned char *data, int size, fz_colorspace *defcs
fz_try(ctx)
{
- img = fz_new_pixmap(ctx, colorspace, w, h);
+ img = fz_new_pixmap(ctx, colorspace, w, h, 1);
}
fz_catch(ctx)
{
@@ -213,6 +213,7 @@ fz_load_jpx(fz_context *ctx, unsigned char *data, int size, fz_colorspace *defcs
}
p = img->samples;
+ stride = img->stride - w * (n + 1);
for (y = 0; y < h; y++)
{
for (x = 0; x < w; x++)
@@ -231,6 +232,7 @@ fz_load_jpx(fz_context *ctx, unsigned char *data, int size, fz_colorspace *defcs
if (!a)
*p++ = 255;
}
+ p += stride;
}
opj_image_destroy(jpx);
@@ -239,7 +241,7 @@ fz_load_jpx(fz_context *ctx, unsigned char *data, int size, fz_colorspace *defcs
{
if (n == 4)
{
- fz_pixmap *tmp = fz_new_pixmap(ctx, fz_device_rgb(ctx), w, h);
+ fz_pixmap *tmp = fz_new_pixmap(ctx, fz_device_rgb(ctx), w, h, 1);
fz_convert_pixmap(ctx, tmp, img);
fz_drop_pixmap(ctx, img);
img = tmp;
diff --git a/source/fitz/load-png.c b/source/fitz/load-png.c
index 33979d4c..21e6e94e 100644
--- a/source/fitz/load-png.c
+++ b/source/fitz/load-png.c
@@ -500,10 +500,12 @@ png_read_image(fz_context *ctx, struct info *info, unsigned char *p, unsigned in
static fz_pixmap *
png_expand_palette(fz_context *ctx, struct info *info, fz_pixmap *src)
{
- fz_pixmap *dst = fz_new_pixmap(ctx, fz_device_rgb(ctx), src->w, src->h);
+ fz_pixmap *dst = fz_new_pixmap(ctx, fz_device_rgb(ctx), src->w, src->h, 1);
unsigned char *sp = src->samples;
unsigned char *dp = dst->samples;
unsigned int x, y;
+ int dstride = dst->stride - dst->w * dst->n;
+ int sstride = src->stride - src->w * src->n;
dst->xres = src->xres;
dst->yres = src->yres;
@@ -519,6 +521,8 @@ png_expand_palette(fz_context *ctx, struct info *info, fz_pixmap *src)
*dp++ = info->palette[v + 3];
sp += 2;
}
+ sp += sstride;
+ dp += dstride;
}
fz_drop_pixmap(ctx, src);
@@ -536,7 +540,7 @@ png_mask_transparency(struct info *info, fz_pixmap *dst)
for (y = 0; y < info->height; y++)
{
unsigned char *sp = info->samples + (unsigned int)(y * stride);
- unsigned char *dp = dst->samples + (unsigned int)(y * dst->w * dst->n);
+ unsigned char *dp = dst->samples + (unsigned int)(y * dst->stride);
for (x = 0; x < info->width; x++)
{
t = 1;
@@ -568,7 +572,7 @@ fz_load_png(fz_context *ctx, unsigned char *p, int total)
fz_try(ctx)
{
- image = fz_new_pixmap(ctx, colorspace, png.width, png.height);
+ image = fz_new_pixmap(ctx, colorspace, png.width, png.height, 1);
}
fz_catch(ctx)
{
diff --git a/source/fitz/load-tiff.c b/source/fitz/load-tiff.c
index 2002c61a..f7661a8d 100644
--- a/source/fitz/load-tiff.c
+++ b/source/fitz/load-tiff.c
@@ -849,7 +849,7 @@ fz_load_tiff_subimage(fz_context *ctx, unsigned char *buf, int len, int subimage
fz_swap_tiff_byte_order(tiff.samples, tiff.imagewidth * tiff.imagelength * tiff.samplesperpixel);
/* Expand into fz_pixmap struct */
- image = fz_new_pixmap(ctx, tiff.colorspace, tiff.imagewidth, tiff.imagelength);
+ image = fz_new_pixmap(ctx, tiff.colorspace, tiff.imagewidth, tiff.imagelength, 1);
image->xres = tiff.xresolution;
image->yres = tiff.yresolution;
@@ -861,7 +861,7 @@ fz_load_tiff_subimage(fz_context *ctx, unsigned char *buf, int len, int subimage
/* CMYK is a subtractive colorspace, we want additive for premul alpha */
if (image->n == 5)
{
- fz_pixmap *rgb = fz_new_pixmap(ctx, fz_device_rgb(ctx), image->w, image->h);
+ fz_pixmap *rgb = fz_new_pixmap(ctx, fz_device_rgb(ctx), image->w, image->h, 1);
fz_convert_pixmap(ctx, rgb, image);
rgb->xres = image->xres;
rgb->yres = image->yres;
diff --git a/source/fitz/output-cbz.c b/source/fitz/output-cbz.c
index d9aff180..4c6d0ca0 100644
--- a/source/fitz/output-cbz.c
+++ b/source/fitz/output-cbz.c
@@ -30,7 +30,7 @@ cbz_begin_page(fz_context *ctx, fz_document_writer *wri_, const fz_rect *mediabo
fz_transform_rect(&bbox, ctm);
fz_round_rect(&ibbox, &bbox);
- wri->pixmap = fz_new_pixmap_with_bbox(ctx, fz_device_rgb(ctx), &ibbox);
+ wri->pixmap = fz_new_pixmap_with_bbox(ctx, fz_device_rgb(ctx), &ibbox, 1);
fz_clear_pixmap_with_value(ctx, wri->pixmap, 0xFF);
return fz_new_draw_device(ctx, wri->pixmap);
diff --git a/source/fitz/output-pcl.c b/source/fitz/output-pcl.c
index e37cce85..6d0a24a6 100644
--- a/source/fitz/output-pcl.c
+++ b/source/fitz/output-pcl.c
@@ -687,7 +687,7 @@ fz_write_pixmap_as_pcl(fz_context *ctx, fz_output *out, const fz_pixmap *pixmap,
pcoc = fz_write_color_pcl_header(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->xres, pixmap->yres, 0, pcl);
fz_try(ctx)
- fz_write_color_pcl_band(ctx, out, pcoc, pixmap->w, pixmap->h, pixmap->n, 0, 0, pixmap->samples);
+ fz_write_color_pcl_band(ctx, out, pcoc, pixmap->w, pixmap->h, pixmap->n, pixmap->stride, 0, 0, pixmap->samples);
fz_always(ctx)
fz_write_color_pcl_trailer(ctx, out, pcoc);
fz_catch(ctx)
@@ -777,7 +777,7 @@ fz_color_pcl_output_context *fz_write_color_pcl_header(fz_context *ctx, fz_outpu
return pcoc;
}
-void fz_write_color_pcl_band(fz_context *ctx, fz_output *out, fz_color_pcl_output_context *pcoc, int w, int h, int n, int band, int bandheight, unsigned char *sp)
+void fz_write_color_pcl_band(fz_context *ctx, fz_output *out, fz_color_pcl_output_context *pcoc, int w, int h, int n, int stride, int band, int bandheight, unsigned char *sp)
{
int y, ss, ds, seed_valid, fill;
unsigned char *prev;
@@ -839,14 +839,14 @@ void fz_write_color_pcl_band(fz_context *ctx, fz_output *out, fz_color_pcl_outpu
if (seed_valid && fill + 5 <= 32767 && memcmp(curr, prev, ds) == 0)
{
int count = 1;
- sp += ss;
+ sp += stride;
y++;
while (count < 32767 && y < h)
{
- if (memcmp(sp-ss, sp, ss) != 0)
+ if (memcmp(sp-stride, sp, ss) != 0)
break;
count++;
- sp += ss;
+ sp += stride;
y++;
}
comp[fill++] = 5; /* Duplicate row */
@@ -900,7 +900,7 @@ void fz_write_color_pcl_band(fz_context *ctx, fz_output *out, fz_color_pcl_outpu
/* curr becomes prev */
tmp = prev; prev = curr; curr = tmp;
- sp += ss;
+ sp += stride;
y++;
}
}
diff --git a/source/fitz/output-ps.c b/source/fitz/output-ps.c
index e80a3f00..1c4f5103 100644
--- a/source/fitz/output-ps.c
+++ b/source/fitz/output-ps.c
@@ -128,7 +128,7 @@ void fz_write_pixmap_as_ps(fz_context *ctx, fz_output *out, const fz_pixmap *pix
fz_try(ctx)
{
- fz_write_ps_band(ctx, out, psoc, pixmap->w, pixmap->h, pixmap->n, 0, 0, pixmap->samples);
+ fz_write_ps_band(ctx, out, psoc, pixmap->w, pixmap->h, pixmap->n, pixmap->stride, 0, 0, pixmap->samples);
}
fz_always(ctx)
{
@@ -153,7 +153,7 @@ void fz_save_pixmap_as_ps(fz_context *ctx, fz_pixmap *pixmap, char *filename, in
fz_rethrow(ctx);
}
-void fz_write_ps_band(fz_context *ctx, fz_output *out, fz_ps_output_context *psoc, int w, int h, int n, int band, int bandheight, unsigned char *samples)
+void fz_write_ps_band(fz_context *ctx, fz_output *out, fz_ps_output_context *psoc, int w, int h, int n, int stride, int band, int bandheight, unsigned char *samples)
{
int x, y, i, err;
int required_input;
@@ -185,12 +185,15 @@ void fz_write_ps_band(fz_context *ctx, fz_output *out, fz_ps_output_context *pso
o = psoc->input;
for (y = 0; y < bandheight; y++)
+ {
for (x = 0; x < w; x++)
{
for (i = n-1; i > 0; i--)
*o++ = *samples++;
samples++;
}
+ samples += stride - w*n;
+ }
psoc->stream.next_in = (Bytef*)psoc->input;
psoc->stream.avail_in = required_input;
diff --git a/source/fitz/output-pwg.c b/source/fitz/output-pwg.c
index 9302009e..50e25a13 100644
--- a/source/fitz/output-pwg.c
+++ b/source/fitz/output-pwg.c
@@ -91,7 +91,7 @@ void
fz_write_pixmap_as_pwg_page(fz_context *ctx, fz_output *out, const fz_pixmap *pixmap, const fz_pwg_options *pwg)
{
unsigned char *sp;
- int y, x, sn, dn, ss;
+ int y, x, sn, dn, ss, ss2;
if (!out || !pixmap)
return;
@@ -109,17 +109,18 @@ fz_write_pixmap_as_pwg_page(fz_context *ctx, fz_output *out, const fz_pixmap *pi
/* Now output the actual bitmap, using a packbits like compression */
sp = pixmap->samples;
ss = pixmap->w * sn;
+ ss2 = pixmap->stride;
y = 0;
while (y < pixmap->h)
{
int yrep;
- assert(sp == pixmap->samples + y * ss);
+ assert(sp == pixmap->samples + y * ss2);
/* Count the number of times this line is repeated */
for (yrep = 1; yrep < 256 && y+yrep < pixmap->h; yrep++)
{
- if (memcmp(sp, sp + yrep * ss, ss) != 0)
+ if (memcmp(sp, sp + yrep * ss2, ss) != 0)
break;
}
fz_write_byte(ctx, out, yrep-1);
@@ -130,7 +131,7 @@ fz_write_pixmap_as_pwg_page(fz_context *ctx, fz_output *out, const fz_pixmap *pi
{
int d;
- assert(sp == pixmap->samples + y * ss + x * sn);
+ assert(sp == pixmap->samples + y * ss2 + x * sn);
/* How far do we have to look to find a repeated value? */
for (d = 1; d < 128 && x+d < pixmap->w; d++)
@@ -169,7 +170,7 @@ fz_write_pixmap_as_pwg_page(fz_context *ctx, fz_output *out, const fz_pixmap *pi
}
/* Move to the next line */
- sp += ss*(yrep-1);
+ sp += ss2*(yrep-1);
y += yrep;
}
}
diff --git a/source/fitz/paint-glyph.h b/source/fitz/paint-glyph.h
index 42b58b97..824adaf2 100644
--- a/source/fitz/paint-glyph.h
+++ b/source/fitz/paint-glyph.h
@@ -9,25 +9,38 @@
#define NAME solid
#endif
-#define FUNCTION_NAMER(NAME,N) fz_paint_glyph_##NAME##_##N
-#define FUNCTION_NAME(NAME,N) FUNCTION_NAMER(NAME,N)
+#ifdef DA
+#define NAME2 _da
+#else
+#define NAME2
+#endif
+
+#define FUNCTION_NAMER(NAME,N,NAME2) fz_paint_glyph_##NAME##_##N##NAME2
+#define FUNCTION_NAME(NAME,N,NAME2) FUNCTION_NAMER(NAME,N,NAME2)
static inline void
-FUNCTION_NAME(NAME,N)(const unsigned char * restrict colorbv,
+FUNCTION_NAME(NAME,N,NAME2)(const unsigned char * restrict colorbv,
#ifndef N
- int n,
+ const int n1,
#endif
int span, unsigned char * restrict dp, const fz_glyph * restrict glyph, int w, int h, int skip_x, int skip_y)
{
#ifdef N
- const int n = N;
+ const int n1 = N;
+#endif
+#ifdef DA
+ const int n = n1 + 1;
+#else
+ const int n = n1;
#endif
#ifdef ALPHA
- int sa = FZ_EXPAND(colorbv[n-1]);
+ int sa = FZ_EXPAND(colorbv[n1]);
#else
-#if defined(N) && N == 2
+#if defined(N) && N == 1 && defined(DA)
const uint16_t color = *(const uint16_t *)colorbv;
-#elif defined(N) && N == 4
+#elif defined(N) && N == 3 && defined(DA)
+ const uint32_t color = *(const uint32_t *)colorbv;
+#elif defined(N) && N == 4 && !defined(DA)
const uint32_t color = *(const uint32_t *)colorbv;
#endif
#endif
@@ -120,42 +133,68 @@ solid_run:
do
{
#ifdef ALPHA
-#if defined(N) && N == 2
+#if defined(N) && N == 1
ddp[0] = FZ_BLEND(colorbv[0], ddp[0], sa);
+#ifdef DA
ddp[1] = FZ_BLEND(0xFF, ddp[1], sa);
ddp += 2;
-#elif defined(N) && N == 4
+#else
+ ddp++;
+#endif
+#elif defined(N) && N == 3
ddp[0] = FZ_BLEND(colorbv[0], ddp[0], sa);
ddp[1] = FZ_BLEND(colorbv[1], ddp[1], sa);
ddp[2] = FZ_BLEND(colorbv[2], ddp[2], sa);
+#ifdef DA
ddp[3] = FZ_BLEND(0xFF, ddp[3], sa);
ddp += 4;
-#elif defined(N) && N == 5
+#else
+ ddp += 3;
+#endif
+#elif defined(N) && N == 4
ddp[0] = FZ_BLEND(colorbv[0], ddp[0], sa);
ddp[1] = FZ_BLEND(colorbv[1], ddp[1], sa);
ddp[2] = FZ_BLEND(colorbv[2], ddp[2], sa);
ddp[3] = FZ_BLEND(colorbv[3], ddp[3], sa);
+#ifdef DA
ddp[4] = FZ_BLEND(0xFF, ddp[4], sa);
ddp += 5;
#else
+ ddp += 4;
+#endif
+#else
int k = 0;
do
{
*ddp = FZ_BLEND(colorbv[k++], *ddp, sa);
ddp++;
}
- while (k != n-1);
+ while (k != n);
+#ifdef DA
*ddp = FZ_BLEND(0xFF, *ddp, sa);
ddp++;
#endif
+#endif
#else
-#if defined(N) && N == 2
+#if defined(N) && N == 1
+#ifdef DA
*(uint16_t *)ddp = color;
ddp += 2;
-#elif defined(N) && N == 4
+#else
+ *ddp++ = colorbv[0];
+#endif
+#elif defined(N) && N == 3
+#ifdef DA
*(uint32_t *)ddp = color;
ddp += 4;
-#elif defined(N) && N == 5
+#else
+ ddp[0] = colorbv[0];
+ ddp[1] = colorbv[1];
+ ddp[2] = colorbv[2];
+ ddp += 3;
+#endif
+#elif defined(N) && N == 4
+#ifdef DA
ddp[0] = colorbv[0];
ddp[1] = colorbv[1];
ddp[2] = colorbv[2];
@@ -163,6 +202,10 @@ solid_run:
ddp[4] = colorbv[4];
ddp += 5;
#else
+ *(uint32_t *)ddp = color;
+ ddp += 4;
+#endif
+#else
int k = 0;
do
{
@@ -192,33 +235,47 @@ intermediate_run:
a = FZ_EXPAND(a);
#endif
(void)k;
-#if defined(N) && N == 2
+#if defined(N) && N == 1
ddp[0] = FZ_BLEND(colorbv[0], ddp[0], a);
+#ifdef DA
ddp[1] = FZ_BLEND(0xFF, ddp[1], a);
ddp += 2;
-#elif defined(N) && N == 4
+#else
+ ddp++;
+#endif
+#elif defined(N) && N == 3
ddp[0] = FZ_BLEND(colorbv[0], ddp[0], a);
ddp[1] = FZ_BLEND(colorbv[1], ddp[1], a);
ddp[2] = FZ_BLEND(colorbv[2], ddp[2], a);
+#ifdef DA
ddp[3] = FZ_BLEND(0xFF, ddp[3], a);
ddp += 4;
-#elif defined(N) && N == 5
+#else
+ ddp += 3;
+#endif
+#elif defined(N) && N == 4
ddp[0] = FZ_BLEND(colorbv[0], ddp[0], a);
ddp[1] = FZ_BLEND(colorbv[1], ddp[1], a);
ddp[2] = FZ_BLEND(colorbv[2], ddp[2], a);
ddp[3] = FZ_BLEND(colorbv[3], ddp[3], a);
+#ifdef DA
ddp[4] = FZ_BLEND(0xFF, ddp[4], a);
ddp += 5;
#else
+ ddp += 4;
+#endif
+#else
do
{
*ddp = FZ_BLEND(colorbv[k++], *ddp, a);
ddp++;
}
- while (k != n-1);
+ while (k != n1);
+#ifdef DA
*ddp = FZ_BLEND(0xFF, *ddp, a);
ddp++;
#endif
+#endif
}
while (--len);
break;
@@ -233,6 +290,8 @@ intermediate_run:
#undef NAME
#undef ALPHA
+#undef NAME2
+#undef DA
#undef N
#undef FUNCTION_NAMER
#undef FUNCTION_NAME
diff --git a/source/fitz/pixmap.c b/source/fitz/pixmap.c
index fca6f733..e0d24265 100644
--- a/source/fitz/pixmap.c
+++ b/source/fitz/pixmap.c
@@ -25,29 +25,41 @@ fz_drop_pixmap_imp(fz_context *ctx, fz_storable *pix_)
}
fz_pixmap *
-fz_new_pixmap_with_data(fz_context *ctx, fz_colorspace *colorspace, int w, int h, unsigned char *samples)
+fz_new_pixmap_with_data(fz_context *ctx, fz_colorspace *colorspace, int w, int h, int alpha, int stride, unsigned char *samples)
{
fz_pixmap *pix;
+ int n;
if (w < 0 || h < 0)
fz_throw(ctx, FZ_ERROR_GENERIC, "Illegal dimensions for pixmap %d %d", w, h);
+ n = alpha + (colorspace ? colorspace->n : 0);
+ if (stride < n*w && stride > -n*w)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "Illegal stride for pixmap (n=%d w=%d, stride=%d)", n, w, stride);
+ if (samples == NULL && stride < n*w)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "Illegal -ve stride for pixmap without data");
+
pix = fz_malloc_struct(ctx, fz_pixmap);
FZ_INIT_STORABLE(pix, 1, fz_drop_pixmap_imp);
pix->x = 0;
pix->y = 0;
pix->w = w;
pix->h = h;
+ pix->alpha = alpha = !!alpha;
pix->interpolate = 1;
pix->xres = 96;
pix->yres = 96;
pix->colorspace = NULL;
- pix->n = 1;
+ pix->n = n;
+ pix->stride = stride;
if (colorspace)
{
pix->colorspace = fz_keep_colorspace(ctx, colorspace);
- pix->n = 1 + colorspace->n;
+ }
+ else
+ {
+ assert(alpha);
}
pix->samples = samples;
@@ -59,9 +71,9 @@ fz_new_pixmap_with_data(fz_context *ctx, fz_colorspace *colorspace, int w, int h
{
fz_try(ctx)
{
- if (pix->w + pix->n - 1 > INT_MAX / pix->n)
+ if (pix->stride - 1 > INT_MAX / pix->n)
fz_throw(ctx, FZ_ERROR_GENERIC, "overly wide image");
- pix->samples = fz_malloc_array(ctx, pix->h, pix->w * pix->n);
+ pix->samples = fz_malloc_array(ctx, pix->h, pix->stride);
}
fz_catch(ctx)
{
@@ -77,25 +89,28 @@ fz_new_pixmap_with_data(fz_context *ctx, fz_colorspace *colorspace, int w, int h
}
fz_pixmap *
-fz_new_pixmap(fz_context *ctx, fz_colorspace *colorspace, int w, int h)
+fz_new_pixmap(fz_context *ctx, fz_colorspace *colorspace, int w, int h, int alpha)
{
- return fz_new_pixmap_with_data(ctx, colorspace, w, h, NULL);
+ int stride = ((colorspace ? colorspace->n : 0) + alpha) * w;
+ return fz_new_pixmap_with_data(ctx, colorspace, w, h, alpha, stride, NULL);
}
fz_pixmap *
-fz_new_pixmap_with_bbox(fz_context *ctx, fz_colorspace *colorspace, const fz_irect *r)
+fz_new_pixmap_with_bbox(fz_context *ctx, fz_colorspace *colorspace, const fz_irect *r, int alpha)
{
fz_pixmap *pixmap;
- pixmap = fz_new_pixmap(ctx, colorspace, r->x1 - r->x0, r->y1 - r->y0);
+ pixmap = fz_new_pixmap(ctx, colorspace, r->x1 - r->x0, r->y1 - r->y0, alpha);
pixmap->x = r->x0;
pixmap->y = r->y0;
return pixmap;
}
fz_pixmap *
-fz_new_pixmap_with_bbox_and_data(fz_context *ctx, fz_colorspace *colorspace, const fz_irect *r, unsigned char *samples)
+fz_new_pixmap_with_bbox_and_data(fz_context *ctx, fz_colorspace *colorspace, const fz_irect *r, int alpha, unsigned char *samples)
{
- fz_pixmap *pixmap = fz_new_pixmap_with_data(ctx, colorspace, r->x1 - r->x0, r->y1 - r->y0, samples);
+ int w = r->x1 - r->x0;
+ int stride = ((colorspace ? colorspace->n : 0) + alpha) * w;
+ fz_pixmap *pixmap = fz_new_pixmap_with_data(ctx, colorspace, w, r->y1 - r->y0, alpha, stride, samples);
pixmap->x = r->x0;
pixmap->y = r->y0;
return pixmap;
@@ -160,9 +175,15 @@ fz_pixmap_components(fz_context *ctx, fz_pixmap *pix)
}
int
+fz_pixmap_colorants(fz_context *ctx, fz_pixmap *pix)
+{
+ return pix->n - pix->alpha;
+}
+
+int
fz_pixmap_stride(fz_context *ctx, fz_pixmap *pix)
{
- return pix->w * pix->n;
+ return pix->stride;
}
unsigned char *
@@ -173,12 +194,6 @@ fz_pixmap_samples(fz_context *ctx, fz_pixmap *pix)
return pix->samples;
}
-void
-fz_clear_pixmap(fz_context *ctx, fz_pixmap *pix)
-{
- memset(pix->samples, 0, (unsigned int)(pix->w * pix->h * pix->n));
-}
-
/*
The slowest routine in most CMYK rendering profiles.
We therefore spend some effort to improve it. Rather than
@@ -238,87 +253,202 @@ clear_cmyk_bitmap(unsigned char *samples, int c, int value)
}
#else
static void
-clear_cmyk_bitmap(unsigned char *samples, int c, int value)
+clear_cmyk_bitmap(unsigned char *samples, int w, int h, int stride, int value, int alpha)
{
- union
- {
- uint8_t bytes[20];
- uint32_t words[5];
- } d;
uint32_t *s = (uint32_t *)(void *)samples;
uint8_t *t;
- d.words[0] = 0;
- d.words[1] = 0;
- d.words[2] = 0;
- d.words[3] = 0;
- d.words[4] = 0;
- d.bytes[3] = value;
- d.bytes[4] = 255;
- d.bytes[8] = value;
- d.bytes[9] = 255;
- d.bytes[13] = value;
- d.bytes[14] = 255;
- d.bytes[18] = value;
- d.bytes[19] = 255;
-
- c -= 3;
+ if (alpha)
{
- const int a0 = d.words[0];
- const int a1 = d.words[1];
- const int a2 = d.words[2];
- const int a3 = d.words[3];
- const int a4 = d.words[4];
- while (c > 0)
+ int c = w;
+ stride -= w*5;
+ if (stride == 0)
+ {
+ /* We can do it all fast (except for maybe a few stragglers) */
+ union
+ {
+ uint8_t bytes[20];
+ uint32_t words[5];
+ } d;
+
+ c *= h;
+ h = 1;
+
+ d.words[0] = 0;
+ d.words[1] = 0;
+ d.words[2] = 0;
+ d.words[3] = 0;
+ d.words[4] = 0;
+ d.bytes[3] = value;
+ d.bytes[4] = 255;
+ d.bytes[8] = value;
+ d.bytes[9] = 255;
+ d.bytes[13] = value;
+ d.bytes[14] = 255;
+ d.bytes[18] = value;
+ d.bytes[19] = 255;
+
+ c -= 3;
+ {
+ const uint32_t a0 = d.words[0];
+ const uint32_t a1 = d.words[1];
+ const uint32_t a2 = d.words[2];
+ const uint32_t a3 = d.words[3];
+ const uint32_t a4 = d.words[4];
+ while (c > 0)
+ {
+ *s++ = a0;
+ *s++ = a1;
+ *s++ = a2;
+ *s++ = a3;
+ *s++ = a4;
+ c -= 4;
+ }
+ }
+ c += 3;
+ }
+ t = (unsigned char *)s;
+ w = c;
+ while (h--)
{
- *s++ = a0;
- *s++ = a1;
- *s++ = a2;
- *s++ = a3;
- *s++ = a4;
- c -= 4;
+ c = w;
+ while (c > 0)
+ {
+ *t++ = 0;
+ *t++ = 0;
+ *t++ = 0;
+ *t++ = value;
+ *t++ = 255;
+ c--;
+ }
+ t += stride;
}
}
- c += 3;
- t = (unsigned char *)s;
- while (c > 0)
+ else
{
- *t++ = 0;
- *t++ = 0;
- *t++ = 0;
- *t++ = value;
- *t++ = 255;
- c--;
+ stride -= w*4;
+ if ((stride & 3)== 0)
+ {
+ /* We can do it all fast */
+ union
+ {
+ uint8_t bytes[4];
+ uint32_t word;
+ } d;
+
+ d.word = 0;
+ d.bytes[3] = value;
+ w *= h;
+
+ {
+ const uint32_t a0 = d.word;
+ while (w > 0)
+ {
+ *s++ = a0;
+ w--;
+ }
+ s += (stride>>2);
+ }
+ }
+ else
+ {
+ t = (unsigned char *)s;
+ while (h--)
+ {
+ int c = w;
+ while (c > 0)
+ {
+ *t++ = 0;
+ *t++ = 0;
+ *t++ = 0;
+ *t++ = value;
+ c--;
+ }
+ t += stride;
+ }
+ }
}
}
#endif
void
+fz_clear_pixmap(fz_context *ctx, fz_pixmap *pix)
+{
+ int stride = pix->w * pix->n;
+ int h = pix->h;
+ unsigned char *s = pix->samples;
+ if (stride == pix->stride)
+ {
+ stride *= h;
+ h = 1;
+ }
+ if (pix->alpha)
+ {
+ while (h--)
+ {
+ memset(s, 0, (unsigned int)stride);
+ s += pix->stride;
+ }
+ }
+ else
+ {
+ /* FIXME: Not right for CMYK or other subtractive spaces */
+ while (h--)
+ {
+ memset(s, 0xff, (unsigned int)stride);
+ s += pix->stride;
+ }
+ }
+}
+
+void
fz_clear_pixmap_with_value(fz_context *ctx, fz_pixmap *pix, int value)
{
+ unsigned char *s;
+ int w, h, n, stride, len;
+ int alpha = pix->alpha;
+
/* CMYK needs special handling (and potentially any other subtractive colorspaces) */
if (pix->colorspace && pix->colorspace->n == 4)
{
- clear_cmyk_bitmap(pix->samples, pix->w * pix->h, 255-value);
+ clear_cmyk_bitmap(pix->samples, pix->w, pix->h, pix->stride, 255-value, pix->alpha);
return;
}
- if (value == 255)
+ w = pix->w;
+ h = pix->h;
+ n = pix->n;
+ stride = pix->stride;
+ len = w * n;
+
+ s = pix->samples;
+ if (value == 255 || !alpha)
{
- memset(pix->samples, 255, (unsigned int)(pix->w * pix->h * pix->n));
+ if (stride == len)
+ {
+ len *= h;
+ h = 1;
+ }
+ while (h--)
+ {
+ memset(s, value, (unsigned int)len);
+ s += stride;
+ }
}
else
{
int k, x, y;
- unsigned char *s = pix->samples;
+ stride -= len;
for (y = 0; y < pix->h; y++)
{
for (x = 0; x < pix->w; x++)
{
for (k = 0; k < pix->n - 1; k++)
*s++ = value;
- *s++ = 255;
+ if (alpha)
+ *s++ = 255;
}
+ s += stride;
}
}
}
@@ -339,9 +469,9 @@ fz_copy_pixmap_rect(fz_context *ctx, fz_pixmap *dest, fz_pixmap *src, const fz_i
if (w <= 0 || y <= 0)
return;
- srcspan = src->w * src->n;
+ srcspan = src->stride;
srcp = src->samples + (unsigned int)(srcspan * (local_b.y0 - src->y) + src->n * (local_b.x0 - src->x));
- destspan = dest->w * dest->n;
+ destspan = dest->stride;
destp = dest->samples + (unsigned int)(destspan * (local_b.y0 - dest->y) + dest->n * (local_b.x0 - dest->x));
if (src->n == dest->n)
@@ -376,6 +506,10 @@ fz_copy_pixmap_rect(fz_context *ctx, fz_pixmap *dest, fz_pixmap *src, const fz_i
}
while (--y);
}
+ else if (src->n == 1 + src->alpha && dest->n == 3 + dest->alpha)
+ {
+ assert("FIXME" == NULL);
+ }
else if (src->n == 4 && dest->n == 2)
{
/* Copy, and convert from rgb+alpha to grey+alpha */
@@ -397,6 +531,10 @@ fz_copy_pixmap_rect(fz_context *ctx, fz_pixmap *dest, fz_pixmap *src, const fz_i
}
while (--y);
}
+ else if (src->n == 3 + src->alpha && dest->n == 1 + dest->alpha)
+ {
+ assert("FIXME" == NULL);
+ }
else
{
/* FIXME: Crap conversion */
@@ -439,7 +577,7 @@ fz_clear_pixmap_rect_with_value(fz_context *ctx, fz_pixmap *dest, int value, con
if (w <= 0 || y <= 0)
return;
- destspan = dest->w * dest->n;
+ destspan = dest->stride;
destp = dest->samples + (unsigned int)(destspan * (local_b.y0 - dest->y) + dest->n * (local_b.x0 - dest->x));
/* CMYK needs special handling (and potentially any other subtractive colorspaces) */
@@ -495,6 +633,7 @@ fz_premultiply_pixmap(fz_context *ctx, fz_pixmap *pix)
unsigned char *s = pix->samples;
unsigned char a;
int k, x, y;
+ int stride = pix->stride - pix->w * pix->n;
for (y = 0; y < pix->h; y++)
{
@@ -505,6 +644,7 @@ fz_premultiply_pixmap(fz_context *ctx, fz_pixmap *pix)
s[k] = fz_mul255(s[k], a);
s += pix->n;
}
+ s += stride;
}
}
@@ -514,6 +654,7 @@ fz_unmultiply_pixmap(fz_context *ctx, fz_pixmap *pix)
unsigned char *s = pix->samples;
int a, inva;
int k, x, y;
+ int stride = pix->stride - pix->w * pix->n;
for (y = 0; y < pix->h; y++)
{
@@ -525,6 +666,7 @@ fz_unmultiply_pixmap(fz_context *ctx, fz_pixmap *pix)
s[k] = (s[k] * inva) >> 8;
s += pix->n;
}
+ s += stride;
}
}
@@ -533,22 +675,28 @@ fz_alpha_from_gray(fz_context *ctx, fz_pixmap *gray, int luminosity)
{
fz_pixmap *alpha;
unsigned char *sp, *dp;
- int len;
+ int w, h, sstride, dstride;
fz_irect bbox;
- assert(gray->n == 2);
+ assert(gray->n == 1);
- alpha = fz_new_pixmap_with_bbox(ctx, NULL, fz_pixmap_bbox(ctx, gray, &bbox));
+ alpha = fz_new_pixmap_with_bbox(ctx, NULL, fz_pixmap_bbox(ctx, gray, &bbox), 1);
dp = alpha->samples;
+ dstride = alpha->stride - alpha->w;
sp = gray->samples;
- if (!luminosity)
- sp ++;
+ sstride = gray->stride - gray->w;
- len = gray->w * gray->h;
- while (len--)
+ h = gray->h;
+ while (h--)
{
- *dp++ = sp[0];
- sp += 2;
+ w = gray->w;
+ while (w--)
+ {
+ *dp++ = sp[0];
+ sp++;
+ }
+ sp += sstride;
+ dp += dstride;
}
return alpha;
@@ -577,26 +725,30 @@ fz_tint_pixmap(fz_context *ctx, fz_pixmap *pix, int r, int g, int b)
if (pix->n == 4)
{
- for (x = 0; x < pix->w; x++)
+ assert(pix->alpha);
+ for (y = 0; y < pix->h; y++)
{
- for (y = 0; y < pix->h; y++)
+ for (x = 0; x < pix->w; x++)
{
s[0] = fz_mul255(s[0], r);
s[1] = fz_mul255(s[1], g);
s[2] = fz_mul255(s[2], b);
s += 4;
}
+ s += pix->stride - pix->w * 4;
}
}
else if (pix->n == 2)
{
- for (x = 0; x < pix->w; x++)
+ assert(pix->alpha);
+ for (y = 0; y < pix->h; y++)
{
- for (y = 0; y < pix->h; y++)
+ for (x = 0; x < pix->w; x++)
{
*s = fz_mul255(*s, g);
s += 2;
}
+ s += pix->stride - pix->w * 2;
}
}
}
@@ -615,6 +767,7 @@ fz_invert_pixmap(fz_context *ctx, fz_pixmap *pix)
s[k] = 255 - s[k];
s += pix->n;
}
+ s += pix->stride - pix->w * pix->n;
}
}
@@ -630,7 +783,7 @@ void fz_invert_pixmap_rect(fz_context *ctx, fz_pixmap *image, const fz_irect *re
for (y = y0; y < y1; y++)
{
- p = image->samples + (unsigned int)((y * image->w + x0) * image->n);
+ p = image->samples + (unsigned int)((y * image->stride) + (x0 * image->n));
for (x = x0; x < x1; x++)
{
for (n = image->n; n > 1; n--, p++)
@@ -658,6 +811,7 @@ fz_gamma_pixmap(fz_context *ctx, fz_pixmap *pix, float gamma)
s[k] = gamma_map[s[k]];
s += pix->n;
}
+ s += pix->stride - pix->w * pix->n;
}
}
@@ -668,19 +822,19 @@ fz_gamma_pixmap(fz_context *ctx, fz_pixmap *pix, float gamma)
void
fz_write_pnm_header(fz_context *ctx, fz_output *out, int w, int h, int n)
{
- if (n != 1 && n != 2 && n != 4)
+ if (n < 1 || n > 4)
fz_throw(ctx, FZ_ERROR_GENERIC, "pixmap must be grayscale or rgb to write as pnm");
if (n == 1 || n == 2)
fz_printf(ctx, out, "P5\n");
- if (n == 4)
+ if (n == 3 || n == 4)
fz_printf(ctx, out, "P6\n");
fz_printf(ctx, out, "%d %d\n", w, h);
fz_printf(ctx, out, "255\n");
}
void
-fz_write_pnm_band(fz_context *ctx, fz_output *out, int w, int h, int n, int band, int bandheight, unsigned char *p)
+fz_write_pnm_band(fz_context *ctx, fz_output *out, int w, int h, int n, int stride, int band, int bandheight, unsigned char *p)
{
char buffer[2*3*4*5*6]; /* Buffer must be a multiple of 2 and 3 at least. */
int len;
@@ -694,58 +848,63 @@ fz_write_pnm_band(fz_context *ctx, fz_output *out, int w, int h, int n, int band
end = h;
end -= start;
- len = w * end;
-
/* Tests show that writing single bytes out at a time
* is appallingly slow. We get a huge improvement
* by collating stuff into buffers first. */
- while (len)
+ while (end--)
{
- int num_written = len;
-
- switch (n)
- {
- case 1:
- /* No collation required */
- fz_write(ctx, out, p, num_written);
- break;
- case 2:
+ len = w;
+ while (len)
{
- char *o = buffer;
- int count;
+ int num_written = len;
- if (num_written > sizeof(buffer))
- num_written = sizeof(buffer);
-
- for (count = num_written; count; count--)
+ switch (n)
{
- *o++ = *p;
- p += 2;
- }
- fz_write(ctx, out, buffer, num_written);
- break;
- }
- case 4:
- {
- char *o = buffer;
- int count;
+ case 1:
+ /* No collation required */
+ fz_write(ctx, out, p, num_written);
+ p += num_written;
+ break;
+ case 2:
+ {
+ char *o = buffer;
+ int count;
- if (num_written > sizeof(buffer)/3)
- num_written = sizeof(buffer)/3;
+ if (num_written > sizeof(buffer))
+ num_written = sizeof(buffer);
- for (count = num_written; count; count--)
+ for (count = num_written; count; count--)
+ {
+ *o++ = *p;
+ p += 2;
+ }
+ fz_write(ctx, out, buffer, num_written);
+ break;
+ }
+ case 3:
+ case 4:
{
- *o++ = p[0];
- *o++ = p[1];
- *o++ = p[2];
- p += 4;
+ char *o = buffer;
+ int count;
+
+ if (num_written > sizeof(buffer)/3)
+ num_written = sizeof(buffer)/3;
+
+ for (count = num_written; count; count--)
+ {
+ *o++ = p[0];
+ *o++ = p[1];
+ *o++ = p[2];
+ p += n;
+ }
+ fz_write(ctx, out, buffer, num_written * 3);
+ break;
}
- fz_write(ctx, out, buffer, num_written * 3);
- break;
- }
+ }
+ len -= num_written;
}
- len -= num_written;
+ p += stride - w*n;
}
}
@@ -753,7 +912,7 @@ void
fz_write_pixmap_as_pnm(fz_context *ctx, fz_output *out, fz_pixmap *pixmap)
{
fz_write_pnm_header(ctx, out, pixmap->w, pixmap->h, pixmap->n);
- fz_write_pnm_band(ctx, out, pixmap->w, pixmap->h, pixmap->n, 0, pixmap->h, pixmap->samples);
+ fz_write_pnm_band(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->stride, 0, pixmap->h, pixmap->samples);
}
void
@@ -761,7 +920,7 @@ fz_save_pixmap_as_pnm(fz_context *ctx, fz_pixmap *pixmap, char *filename)
{
fz_output *out = fz_new_output_with_path(ctx, filename, 0);
fz_write_pnm_header(ctx, out, pixmap->w, pixmap->h, pixmap->n);
- fz_write_pnm_band(ctx, out, pixmap->w, pixmap->h, pixmap->n, 0, pixmap->h, pixmap->samples);
+ fz_write_pnm_band(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->stride, 0, pixmap->h, pixmap->samples);
fz_drop_output(ctx, out);
}
@@ -792,7 +951,7 @@ fz_write_pam_header(fz_context *ctx, fz_output *out, int w, int h, int n, int sa
}
void
-fz_write_pam_band(fz_context *ctx, fz_output *out, int w, int h, int n, int band, int bandheight, unsigned char *sp, int savealpha)
+fz_write_pam_band(fz_context *ctx, fz_output *out, int w, int h, int n, int stride, int band, int bandheight, unsigned char *sp, int savealpha)
{
int y, x;
int start = band * bandheight;
@@ -817,6 +976,7 @@ fz_write_pam_band(fz_context *ctx, fz_output *out, int w, int h, int n, int band
fz_write(ctx, out, sp, dn);
sp += sn;
}
+ sp += stride - w*n;
}
}
@@ -824,7 +984,7 @@ void
fz_write_pixmap_as_pam(fz_context *ctx, fz_output *out, fz_pixmap *pixmap, int savealpha)
{
fz_write_pam_header(ctx, out, pixmap->w, pixmap->h, pixmap->n, savealpha);
- fz_write_pam_band(ctx, out, pixmap->w, pixmap->h, pixmap->n, 0, pixmap->h, pixmap->samples, savealpha);
+ fz_write_pam_band(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->stride, 0, pixmap->h, pixmap->samples, savealpha);
}
void
@@ -834,7 +994,7 @@ fz_save_pixmap_as_pam(fz_context *ctx, fz_pixmap *pixmap, char *filename, int sa
fz_try(ctx)
{
fz_write_pam_header(ctx, out, pixmap->w, pixmap->h, pixmap->n, savealpha);
- fz_write_pam_band(ctx, out, pixmap->w, pixmap->h, pixmap->n, 0, pixmap->h, pixmap->samples, savealpha);
+ fz_write_pam_band(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->stride, 0, pixmap->h, pixmap->samples, savealpha);
}
fz_always(ctx)
fz_drop_output(ctx, out);
@@ -878,8 +1038,8 @@ fz_save_pixmap_as_png(fz_context *ctx, fz_pixmap *pixmap, const char *filename,
fz_try(ctx)
{
- poc = fz_write_png_header(ctx, out, pixmap->w, pixmap->h, pixmap->n, savealpha);
- fz_write_png_band(ctx, out, poc, pixmap->w, pixmap->h, pixmap->n, 0, pixmap->h, pixmap->samples, savealpha);
+ poc = fz_write_png_header(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, savealpha);
+ fz_write_png_band(ctx, out, poc, pixmap->stride, 0, pixmap->h, pixmap->samples);
}
fz_always(ctx)
{
@@ -900,11 +1060,11 @@ fz_write_pixmap_as_png(fz_context *ctx, fz_output *out, const fz_pixmap *pixmap,
if (!out)
return;
- poc = fz_write_png_header(ctx, out, pixmap->w, pixmap->h, pixmap->n, savealpha);
+ poc = fz_write_png_header(ctx, out, pixmap->w, pixmap->h, pixmap->n, pixmap->alpha, savealpha);
fz_try(ctx)
{
- fz_write_png_band(ctx, out, poc, pixmap->w, pixmap->h, pixmap->n, 0, pixmap->h, pixmap->samples, savealpha);
+ fz_write_png_band(ctx, out, poc, pixmap->stride, 0, pixmap->h, pixmap->samples);
}
fz_always(ctx)
{
@@ -922,10 +1082,15 @@ struct fz_png_output_context_s
unsigned char *cdata;
uLong usize, csize;
z_stream stream;
+ int w;
+ int h;
+ int n;
+ int alpha;
+ int savealpha;
};
fz_png_output_context *
-fz_write_png_header(fz_context *ctx, fz_output *out, int w, int h, int n, int savealpha)
+fz_write_png_header(fz_context *ctx, fz_output *out, int w, int h, int n, int alpha, int savealpha)
{
static const unsigned char pngsig[8] = { 137, 80, 78, 71, 13, 10, 26, 10 };
unsigned char head[13];
@@ -935,23 +1100,29 @@ fz_write_png_header(fz_context *ctx, fz_output *out, int w, int h, int n, int sa
if (!out)
return NULL;
- if (n != 1 && n != 2 && n != 4)
- fz_throw(ctx, FZ_ERROR_GENERIC, "pixmap must be grayscale or rgb to write as png");
-
- poc = fz_malloc_struct(ctx, fz_png_output_context);
-
- if (!savealpha && n > 1)
- n--;
+ /* Treat alpha only as greyscale */
+ if (n == 1 && alpha)
+ alpha = 0;
- switch (n)
+ switch (n - alpha)
{
+ case 1: color = (alpha ? 4 : 0); break; /* 0 = Greyscale, 4 = Greyscale + Alpha */
+ case 3: color = (alpha ? 6 : 2); break; /* 2 = RGB, 6 = RGBA */
default:
- case 1: color = 0; break;
- case 2: color = 4; break;
- case 3: color = 2; break;
- case 4: color = 6; break;
+ fz_throw(ctx, FZ_ERROR_GENERIC, "pixmap must be grayscale or rgb to write as png");
}
+ /* If we have no alpha, save no alpha */
+ if (!alpha)
+ savealpha = 0;
+
+ poc = fz_malloc_struct(ctx, fz_png_output_context);
+ poc->w = w;
+ poc->h = h;
+ poc->n = n;
+ poc->alpha = alpha;
+ poc->savealpha = savealpha;
+
big32(head+0, w);
big32(head+4, h);
head[8] = 8; /* depth */
@@ -967,16 +1138,20 @@ fz_write_png_header(fz_context *ctx, fz_output *out, int w, int h, int n, int sa
}
void
-fz_write_png_band(fz_context *ctx, fz_output *out, fz_png_output_context *poc, int w, int h, int n, int band, int bandheight, unsigned char *sp, int savealpha)
+fz_write_png_band(fz_context *ctx, fz_output *out, fz_png_output_context *poc, int stride, int band, int bandheight, unsigned char *sp)
{
unsigned char *dp;
int y, x, k, sn, dn, err, finalband;
+ int w, h, n, alpha, savealpha;
if (!out || !sp || !poc)
return;
- if (n != 1 && n != 2 && n != 4)
- fz_throw(ctx, FZ_ERROR_GENERIC, "pixmap must be grayscale or rgb to write as png");
+ w = poc->w;
+ h = poc->h;
+ n = poc->n;
+ alpha = poc->alpha;
+ savealpha = poc->savealpha;
band *= bandheight;
finalband = (band+bandheight >= h);
@@ -984,9 +1159,7 @@ fz_write_png_band(fz_context *ctx, fz_output *out, fz_png_output_context *poc, i
bandheight = h - band;
sn = n;
- dn = n;
- if (!savealpha && dn > 1)
- dn--;
+ dn = n - alpha + savealpha;
if (poc->udata == NULL)
{
@@ -1015,6 +1188,7 @@ fz_write_png_band(fz_context *ctx, fz_output *out, fz_png_output_context *poc, i
}
dp = poc->udata;
+ stride -= w*sn;
for (y = 0; y < bandheight; y++)
{
*dp++ = 1; /* sub prediction filter */
@@ -1030,6 +1204,7 @@ fz_write_png_band(fz_context *ctx, fz_output *out, fz_png_output_context *poc, i
sp += sn;
dp += dn;
}
+ sp += stride;
}
poc->stream.next_in = (Bytef*)poc->udata;
@@ -1099,7 +1274,7 @@ png_from_pixmap(fz_context *ctx, fz_pixmap *pix, int drop)
{
if (pix->colorspace && pix->colorspace != fz_device_gray(ctx) && pix->colorspace != fz_device_rgb(ctx))
{
- pix2 = fz_new_pixmap(ctx, fz_device_rgb(ctx), pix->w, pix->h);
+ pix2 = fz_new_pixmap(ctx, fz_device_rgb(ctx), pix->w, pix->h, 1);
fz_convert_pixmap(ctx, pix2, pix);
if (drop)
fz_drop_pixmap(ctx, pix);
@@ -1231,12 +1406,17 @@ fz_pixmap_size(fz_context *ctx, fz_pixmap * pix)
fz_pixmap *
fz_new_pixmap_from_8bpp_data(fz_context *ctx, int x, int y, int w, int h, unsigned char *sp, int span)
{
- fz_pixmap *pixmap = fz_new_pixmap(ctx, NULL, w, h);
+ fz_pixmap *pixmap = fz_new_pixmap(ctx, NULL, w, h, 1);
+ int stride = pixmap->stride;
+ unsigned char *s = pixmap->samples;
pixmap->x = x;
pixmap->y = y;
for (y = 0; y < h; y++)
- memcpy(pixmap->samples + y * w, sp + y * span, w);
+ {
+ memcpy(s, sp + y * span, w);
+ s += stride;
+ }
return pixmap;
}
@@ -1244,7 +1424,8 @@ fz_new_pixmap_from_8bpp_data(fz_context *ctx, int x, int y, int w, int h, unsign
fz_pixmap *
fz_new_pixmap_from_1bpp_data(fz_context *ctx, int x, int y, int w, int h, unsigned char *sp, int span)
{
- fz_pixmap *pixmap = fz_new_pixmap(ctx, NULL, w, h);
+ fz_pixmap *pixmap = fz_new_pixmap(ctx, NULL, w, h, 1);
+ int stride = pixmap->stride - pixmap->w;
pixmap->x = x;
pixmap->y = y;
@@ -1261,6 +1442,7 @@ fz_new_pixmap_from_1bpp_data(fz_context *ctx, int x, int y, int w, int h, unsign
if (bit == 0)
bit = 0x80, in++;
}
+ out += stride;
}
return pixmap;
@@ -1458,6 +1640,9 @@ fz_subsample_pixmap(fz_context *ctx, fz_pixmap *tile, int factor)
if (!tile)
return;
+
+ assert(tile->stride >= tile->w * tile->n);
+
s = d = tile->samples;
f = 1<<factor;
w = tile->w;
@@ -1465,11 +1650,11 @@ fz_subsample_pixmap(fz_context *ctx, fz_pixmap *tile, int factor)
n = tile->n;
dst_w = (w + f-1)>>factor;
dst_h = (h + f-1)>>factor;
- fwd = w*n;
+ fwd = tile->stride;
back = f*fwd-n;
back2 = f*n-1;
fwd2 = (f-1)*n;
- fwd3 = (f-1)*fwd;
+ fwd3 = (f-1)*fwd + tile->stride - w * n;
factor *= 2;
#ifdef ARCH_ARM
{
@@ -1583,6 +1768,7 @@ fz_subsample_pixmap(fz_context *ctx, fz_pixmap *tile, int factor)
#endif
tile->w = dst_w;
tile->h = dst_h;
+ tile->stride = dst_w * n;
tile->samples = fz_resize_array(ctx, tile->samples, dst_w * n, dst_h);
}
@@ -1600,6 +1786,43 @@ fz_md5_pixmap(fz_context *ctx, fz_pixmap *pix, unsigned char digest[16])
fz_md5_init(&md5);
if (pix)
- fz_md5_update(&md5, pix->samples, pix->w * pix->h * pix->n);
+ {
+ unsigned char *s = pix->samples;
+ int h = pix->h;
+ int ss = pix->stride;
+ int len = pix->w * pix->n;
+ while (h--)
+ {
+ fz_md5_update(&md5, s, len);
+ s += ss;
+ }
+ }
fz_md5_final(&md5, digest);
}
+
+#ifdef HAVE_VALGRIND
+int fz_valgrind_pixmap(const fz_pixmap *pix)
+{
+ int w, h, n, total;
+ int ww, hh, nn;
+ int stride;
+ const unsigned char *p = pix->samples;
+
+ if (pix == NULL)
+ return;
+
+ total = 0;
+ ww = pix->w;
+ hh = pix->h;
+ nn = pix->n;
+ stride = pix->stride - ww*nn;
+ for (h = 0; h < hh; h++)
+ {
+ for (w = 0; w < ww; w++)
+ for (n = 0; n < nn; n++)
+ if (*p++) total ++;
+ p += stride;
+ }
+ return total;
+}
+#endif /* HAVE_VALGRIND */
diff --git a/source/fitz/svg-device.c b/source/fitz/svg-device.c
index 97a1acca..acc2c5bc 100644
--- a/source/fitz/svg-device.c
+++ b/source/fitz/svg-device.c
@@ -776,7 +776,7 @@ svg_dev_fill_shade(fz_context *ctx, fz_device *dev, fz_shade *shade, const fz_ma
fz_round_rect(&bbox, fz_intersect_rect(fz_bound_shade(ctx, shade, ctm, &rect), &dev->container[dev->container_len-1].scissor));
if (fz_is_empty_irect(&bbox))
return;
- pix = fz_new_pixmap_with_bbox(ctx, fz_device_rgb(ctx), &bbox);
+ pix = fz_new_pixmap_with_bbox(ctx, fz_device_rgb(ctx), &bbox, 1);
fz_clear_pixmap(ctx, pix);
fz_try(ctx)
diff --git a/source/fitz/test-device.c b/source/fitz/test-device.c
index c0fb95f9..15e6a3ff 100644
--- a/source/fitz/test-device.c
+++ b/source/fitz/test-device.c
@@ -127,7 +127,7 @@ fz_test_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_ma
fz_test_device *t = (fz_test_device*)dev;
fz_pixmap *pix;
- unsigned int count, i, k;
+ unsigned int count, i, k, h, sa, ss;
unsigned char *s;
fz_compressed_buffer *buffer;
@@ -177,6 +177,9 @@ fz_test_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_ma
{
*t->is_color = 1;
dev->hints |= FZ_IGNORE_IMAGE;
+ fz_drop_stream(ctx, stream);
+ fz_fin_cached_color_converter(ctx, &cc);
+ fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
break;
}
}
@@ -190,23 +193,30 @@ fz_test_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_ma
if (pix == NULL) /* Should never happen really, but... */
return;
- count = (unsigned int)pix->w * (unsigned int)pix->h;
+ count = pix->w;
+ h = pix->h;
s = pix->samples;
+ sa = pix->alpha;
+ ss = pix->stride - pix->w * pix->n;
if (pix->colorspace == fz_device_rgb(ctx))
{
int threshold_u8 = t->threshold * 255;
- for (i = 0; i < count; i++)
+ while (h--)
{
- if (s[3] != 0 && is_rgb_color_u8(threshold_u8, s[0], s[1], s[2]))
+ for (i = 0; i < count; i++)
{
- *t->is_color = 1;
- dev->hints |= FZ_IGNORE_IMAGE;
- fz_drop_pixmap(ctx, pix);
- fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
- break;
+ if ((!sa || s[3] != 0) && is_rgb_color_u8(threshold_u8, s[0], s[1], s[2]))
+ {
+ *t->is_color = 1;
+ dev->hints |= FZ_IGNORE_IMAGE;
+ fz_drop_pixmap(ctx, pix);
+ fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
+ break;
+ }
+ s += 3 + sa;
}
- s += 4;
+ s += ss;
}
}
else
@@ -215,26 +225,31 @@ fz_test_fill_image(fz_context *ctx, fz_device *dev, fz_image *image, const fz_ma
unsigned int n = (unsigned int)pix->n-1;
fz_init_cached_color_converter(ctx, &cc, fz_device_rgb(ctx), pix->colorspace);
- for (i = 0; i < count; i++)
+ while (h--)
{
- float cs[FZ_MAX_COLORS];
- float ds[FZ_MAX_COLORS];
+ for (i = 0; i < count; i++)
+ {
+ float cs[FZ_MAX_COLORS];
+ float ds[FZ_MAX_COLORS];
- for (k = 0; k < n; k++)
- cs[k] = (*s++) / 255.0f;
- if (*s++ == 0)
- continue;
+ for (k = 0; k < n; k++)
+ cs[k] = (*s++) / 255.0f;
+ if (sa && *s++ == 0)
+ continue;
- cc.convert(ctx, &cc, ds, cs);
+ cc.convert(ctx, &cc, ds, cs);
- if (is_rgb_color(t->threshold, ds[0], ds[1], ds[2]))
- {
- *t->is_color = 1;
- dev->hints |= FZ_IGNORE_IMAGE;
- fz_drop_pixmap(ctx, pix);
- fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
- break;
+ if (is_rgb_color(t->threshold, ds[0], ds[1], ds[2]))
+ {
+ *t->is_color = 1;
+ dev->hints |= FZ_IGNORE_IMAGE;
+ fz_fin_cached_color_converter(ctx, &cc);
+ fz_drop_pixmap(ctx, pix);
+ fz_throw(ctx, FZ_ERROR_ABORT, "Page found as color; stopping interpretation");
+ break;
+ }
}
+ s += ss;
}
fz_fin_cached_color_converter(ctx, &cc);
}
diff --git a/source/fitz/transition.c b/source/fitz/transition.c
index b4da6192..ec7d3f19 100644
--- a/source/fitz/transition.c
+++ b/source/fitz/transition.c
@@ -1,22 +1,40 @@
#include "mupdf/fitz.h"
+/*
+ FIXME: Currently transitions only work with alpha. Our app only
+ uses alpha.
+*/
+
static int
-fade(fz_pixmap *tpix, fz_pixmap *opix, fz_pixmap *npix, int time)
+fade(fz_pixmap *tpix, const fz_pixmap *opix, const fz_pixmap *npix, int time)
{
unsigned char *t, *o, *n;
int size;
+ int h;
+ int tstride, ostride, nstride;
if (!tpix || !opix || !npix || tpix->w != opix->w || opix->w != npix->w || tpix->h != opix->h || opix->h != npix->h || tpix->n != opix->n || opix->n != npix->n)
return 0;
- size = tpix->w * tpix->h * tpix->n;
+ h = tpix->h;
+ size = tpix->w * tpix->n;
+ ostride = opix->stride - size;
+ nstride = npix->stride - size;
+ tstride = tpix->stride - size;
t = tpix->samples;
o = opix->samples;
n = npix->samples;
- while (size-- > 0)
+ while (h--)
{
- int op = *o++;
- int np = *n++;
- *t++ = ((op<<8) + ((np-op) * time) + 0x80)>>8;
+ int ww = size;
+ while (ww-- > 0)
+ {
+ int op = *o++;
+ int np = *n++;
+ *t++ = ((op<<8) + ((np-op) * time) + 0x80)>>8;
+ }
+ o += ostride;
+ n += nstride;
+ t += tstride;
}
return 1;
}
@@ -25,22 +43,26 @@ static int
blind_horiz(fz_pixmap *tpix, fz_pixmap *opix, fz_pixmap *npix, int time)
{
unsigned char *t, *o, *n;
- int blind_height, span, position, y;
+ int blind_height, size, position, y;
+ int tstride, ostride, nstride;
if (!tpix || !opix || !npix || tpix->w != opix->w || opix->w != npix->w || tpix->h != opix->h || opix->h != npix->h || tpix->n != opix->n || opix->n != npix->n)
return 0;
- span = tpix->w * tpix->n;
+ size = tpix->w * tpix->n;
blind_height = (tpix->h+7) / 8;
position = blind_height * time / 256;
+ ostride = opix->stride;
+ nstride = npix->stride;
+ tstride = tpix->stride;
t = tpix->samples;
o = opix->samples;
n = npix->samples;
for (y = 0; y < tpix->h; y++)
{
- memcpy(t, ((y % blind_height) <= position ? n : o), span);
- t += span;
- o += span;
- n += span;
+ memcpy(t, ((y % blind_height) <= position ? n : o), size);
+ t += tstride;
+ o += ostride;
+ n += nstride;
}
return 1;
}
@@ -49,15 +71,19 @@ static int
blind_vertical(fz_pixmap *tpix, fz_pixmap *opix, fz_pixmap *npix, int time)
{
unsigned char *t, *o, *n;
- int blind_width, span, position, y;
+ int blind_width, size, position, y;
+ int tstride, ostride, nstride;
if (!tpix || !opix || !npix || tpix->w != opix->w || opix->w != npix->w || tpix->h != opix->h || opix->h != npix->h || tpix->n != opix->n || opix->n != npix->n)
return 0;
- span = tpix->w * tpix->n;
+ size = tpix->w * tpix->n;
blind_width = (tpix->w+7) / 8;
position = blind_width * time / 256;
blind_width *= tpix->n;
position *= tpix->n;
+ ostride = opix->stride - size;
+ nstride = npix->stride - size;
+ tstride = tpix->stride - size;
t = tpix->samples;
o = opix->samples;
n = npix->samples;
@@ -65,7 +91,7 @@ blind_vertical(fz_pixmap *tpix, fz_pixmap *opix, fz_pixmap *npix, int time)
{
int w, x;
x = 0;
- while ((w = span - x) > 0)
+ while ((w = size - x) > 0)
{
int p;
if (w > blind_width)
@@ -80,6 +106,9 @@ blind_vertical(fz_pixmap *tpix, fz_pixmap *opix, fz_pixmap *npix, int time)
o += w;
n += w;
}
+ o += ostride;
+ n += nstride;
+ t += tstride;
}
return 1;
}
@@ -88,28 +117,32 @@ static int
wipe_tb(fz_pixmap *tpix, fz_pixmap *opix, fz_pixmap *npix, int time)
{
unsigned char *t, *o, *n;
- int span, position, y;
+ int size, position, y;
+ int tstride, ostride, nstride;
if (!tpix || !opix || !npix || tpix->w != opix->w || opix->w != npix->w || tpix->h != opix->h || opix->h != npix->h || tpix->n != opix->n || opix->n != npix->n)
return 0;
- span = tpix->w * tpix->n;
+ size = tpix->w * tpix->n;
position = tpix->h * time / 256;
+ ostride = opix->stride;
+ nstride = npix->stride;
+ tstride = tpix->stride;
t = tpix->samples;
o = opix->samples;
n = npix->samples;
for (y = 0; y < position; y++)
{
- memcpy(t, n, span);
- t += span;
- o += span;
- n += span;
+ memcpy(t, n, size);
+ t += tstride;
+ o += ostride;
+ n += nstride;
}
for (; y < tpix->h; y++)
{
- memcpy(t, o, span);
- t += span;
- o += span;
- n += span;
+ memcpy(t, o, size);
+ t += tstride;
+ o += ostride;
+ n += nstride;
}
return 1;
}
@@ -118,23 +151,27 @@ static int
wipe_lr(fz_pixmap *tpix, fz_pixmap *opix, fz_pixmap *npix, int time)
{
unsigned char *t, *o, *n;
- int span, position, y;
+ int size, position, y;
+ int tstride, ostride, nstride;
if (!tpix || !opix || !npix || tpix->w != opix->w || opix->w != npix->w || tpix->h != opix->h || opix->h != npix->h || tpix->n != opix->n || opix->n != npix->n)
return 0;
- span = tpix->w * tpix->n;
+ size = tpix->w * tpix->n;
position = tpix->w * time / 256;
position *= tpix->n;
+ ostride = opix->stride;
+ nstride = npix->stride;
+ tstride = tpix->stride;
t = tpix->samples;
o = opix->samples + position;
n = npix->samples;
for (y = 0; y < tpix->h; y++)
{
memcpy(t, n, position);
- memcpy(t+position, o, span-position);
- t += span;
- o += span;
- n += span;
+ memcpy(t+position, o, size-position);
+ t += tstride;
+ o += ostride;
+ n += nstride;
}
return 1;
}
diff --git a/source/fitz/util.c b/source/fitz/util.c
index 0d782ba8..01e52e91 100644
--- a/source/fitz/util.c
+++ b/source/fitz/util.c
@@ -43,7 +43,7 @@ fz_new_display_list_from_page_number(fz_context *ctx, fz_document *doc, int numb
}
fz_pixmap *
-fz_new_pixmap_from_display_list(fz_context *ctx, fz_display_list *list, const fz_matrix *ctm, fz_colorspace *cs, int background)
+fz_new_pixmap_from_display_list(fz_context *ctx, fz_display_list *list, const fz_matrix *ctm, fz_colorspace *cs, int alpha)
{
fz_rect rect;
fz_irect irect;
@@ -54,11 +54,11 @@ fz_new_pixmap_from_display_list(fz_context *ctx, fz_display_list *list, const fz
fz_transform_rect(&rect, ctm);
fz_round_rect(&irect, &rect);
- pix = fz_new_pixmap_with_bbox(ctx, cs, &irect);
- if (background)
- fz_clear_pixmap_with_value(ctx, pix, 0xFF);
- else
+ pix = fz_new_pixmap_with_bbox(ctx, cs, &irect, alpha);
+ if (alpha)
fz_clear_pixmap(ctx, pix);
+ else
+ fz_clear_pixmap_with_value(ctx, pix, 0xFF);
fz_try(ctx)
{
@@ -90,7 +90,7 @@ fz_new_pixmap_from_page_contents(fz_context *ctx, fz_page *page, const fz_matrix
fz_transform_rect(&rect, ctm);
fz_round_rect(&irect, &rect);
- pix = fz_new_pixmap_with_bbox(ctx, cs, &irect);
+ pix = fz_new_pixmap_with_bbox(ctx, cs, &irect, 0);
fz_clear_pixmap_with_value(ctx, pix, 0xFF);
fz_try(ctx)
@@ -123,7 +123,7 @@ fz_new_pixmap_from_annot(fz_context *ctx, fz_annot *annot, const fz_matrix *ctm,
fz_transform_rect(&rect, ctm);
fz_round_rect(&irect, &rect);
- pix = fz_new_pixmap_with_bbox(ctx, cs, &irect);
+ pix = fz_new_pixmap_with_bbox(ctx, cs, &irect, 1);
fz_clear_pixmap(ctx, pix);
fz_try(ctx)
@@ -156,7 +156,7 @@ fz_new_pixmap_from_page(fz_context *ctx, fz_page *page, const fz_matrix *ctm, fz
fz_transform_rect(&rect, ctm);
fz_round_rect(&irect, &rect);
- pix = fz_new_pixmap_with_bbox(ctx, cs, &irect);
+ pix = fz_new_pixmap_with_bbox(ctx, cs, &irect, 0);
fz_clear_pixmap_with_value(ctx, pix, 0xFF);
fz_try(ctx)
diff --git a/source/pdf/pdf-image.c b/source/pdf/pdf-image.c
index 51bb4583..3bba27ad 100644
--- a/source/pdf/pdf-image.c
+++ b/source/pdf/pdf-image.c
@@ -40,12 +40,13 @@ pdf_load_image_imp(fz_context *ctx, pdf_document *doc, pdf_obj *rdb, pdf_obj *di
fz_pixmap_image *cimg = (fz_pixmap_image *)image;
fz_pixmap *mask_pixmap;
fz_pixmap *tile = fz_pixmap_image_tile(ctx, cimg);
- if (image->n != 2)
+ if (tile->n != 1)
{
fz_pixmap *gray;
fz_irect bbox;
- fz_warn(ctx, "soft mask should be grayscale");
- gray = fz_new_pixmap_with_bbox(ctx, fz_device_gray(ctx), fz_pixmap_bbox(ctx, tile, &bbox));
+ if (tile->n != 2)
+ fz_warn(ctx, "soft mask should be grayscale");
+ gray = fz_new_pixmap_with_bbox(ctx, fz_device_gray(ctx), fz_pixmap_bbox(ctx, tile, &bbox), 0);
fz_convert_pixmap(ctx, gray, tile);
fz_drop_pixmap(ctx, tile);
tile = gray;
@@ -323,32 +324,44 @@ pdf_add_image(fz_context *ctx, pdf_document *doc, fz_image *image, int mask)
else
{
unsigned int size;
- int n;
+ int n, h;
+ unsigned char *d, *s;
/* Currently, set to maintain resolution; should we consider
* subsampling here according to desired output res? */
pixmap = fz_get_pixmap_from_image(ctx, image, NULL, NULL, NULL, NULL);
colorspace = pixmap->colorspace; /* May be different to image->colorspace! */
- n = (pixmap->n == 1 ? 1 : pixmap->n - 1);
- size = image->w * image->h * n;
+ n = (pixmap->n == 1 ? 1 : pixmap->n - pixmap->alpha);
+ d = buffer->data;
+ s = pixmap->samples;
+ h = image->h;
+ size = image->w * n;
buffer = fz_new_buffer(ctx, size);
buffer->len = size;
- if (pixmap->n == 1)
+ if (pixmap->alpha == 0 || n == 1)
{
- memcpy(buffer->data, pixmap->samples, size);
+ while (h--)
+ {
+ memcpy(d, s, size);
+ d += size;
+ s += pixmap->stride;
+ }
}
else
{
/* Need to remove the alpha plane */
- unsigned char *d = buffer->data;
- unsigned char *s = pixmap->samples;
int mod = n;
- while (size--)
+ int stride = pixmap->stride - pixmap->w * pixmap->n;
+ while (h--)
{
- *d++ = *s++;
- mod--;
- if (mod == 0)
- s++, mod = n;
+ while (size--)
+ {
+ *d++ = *s++;
+ mod--;
+ if (mod == 0)
+ s++, mod = n;
+ }
+ s += stride;
}
}
}
diff --git a/source/pdf/pdf-resources.c b/source/pdf/pdf-resources.c
index 212c57df..b66c0a23 100644
--- a/source/pdf/pdf-resources.c
+++ b/source/pdf/pdf-resources.c
@@ -27,10 +27,18 @@ res_image_get_md5(fz_context *ctx, fz_image *image, unsigned char *digest)
{
fz_pixmap *pixmap;
fz_md5 state;
+ int h;
+ unsigned char *d;
pixmap = fz_get_pixmap_from_image(ctx, image, NULL, NULL, 0, 0);
fz_md5_init(&state);
- fz_md5_update(&state, pixmap->samples, pixmap->w * pixmap->h * pixmap->n);
+ d = pixmap->samples;
+ h = pixmap->h;
+ while (h--)
+ {
+ fz_md5_update(&state, d, pixmap->w * pixmap->n);
+ d += pixmap->stride;
+ }
fz_md5_final(&state, digest);
fz_drop_pixmap(ctx, pixmap);
}
diff --git a/source/tools/mudraw.c b/source/tools/mudraw.c
index a58912a9..b1ab97e9 100644
--- a/source/tools/mudraw.c
+++ b/source/tools/mudraw.c
@@ -363,6 +363,7 @@ static int lowmemory = 0;
static int errored = 0;
static fz_stext_sheet *sheet = NULL;
static fz_colorspace *colorspace;
+static int alpha;
static char *filename;
static int files = 0;
static int num_workers = 0;
@@ -835,7 +836,7 @@ static void dodrawpage(fz_context *ctx, fz_page *page, fz_display_list *list, in
workers[band].tbounds = tbounds;
memset(&workers[band].cookie, 0, sizeof(fz_cookie));
workers[band].list = list;
- workers[band].pix = fz_new_pixmap_with_bbox(ctx, colorspace, &band_ibounds);
+ workers[band].pix = fz_new_pixmap_with_bbox(ctx, colorspace, &band_ibounds, alpha);
fz_pixmap_set_resolution(workers[band].pix, resolution);
DEBUG_THREADS(("Worker %d, Pre-triggering band %d\n", band, band));
SEMAPHORE_TRIGGER(workers[band].start);
@@ -845,7 +846,7 @@ static void dodrawpage(fz_context *ctx, fz_page *page, fz_display_list *list, in
}
else
{
- pix = fz_new_pixmap_with_bbox(ctx, colorspace, &band_ibounds);
+ pix = fz_new_pixmap_with_bbox(ctx, colorspace, &band_ibounds, alpha);
fz_pixmap_set_resolution(pix, resolution);
}
@@ -857,7 +858,7 @@ static void dodrawpage(fz_context *ctx, fz_page *page, fz_display_list *list, in
else if (output_format == OUT_PAM)
fz_write_pam_header(ctx, out, pix->w, totalheight, pix->n, savealpha);
else if (output_format == OUT_PNG)
- poc = fz_write_png_header(ctx, out, pix->w, totalheight, pix->n, savealpha);
+ poc = fz_write_png_header(ctx, out, pix->w, totalheight, pix->n, pix->alpha, savealpha);
else if (output_format == OUT_PBM)
fz_write_pbm_header(ctx, out, pix->w, totalheight);
else if (output_format == OUT_PKM)
@@ -889,11 +890,11 @@ static void dodrawpage(fz_context *ctx, fz_page *page, fz_display_list *list, in
if (output)
{
if (output_format == OUT_PGM || output_format == OUT_PPM || output_format == OUT_PNM)
- fz_write_pnm_band(ctx, out, pix->w, totalheight, pix->n, band, drawheight, pix->samples);
+ fz_write_pnm_band(ctx, out, pix->w, totalheight, pix->n, pix->stride, band, drawheight, pix->samples);
else if (output_format == OUT_PAM)
- fz_write_pam_band(ctx, out, pix->w, totalheight, pix->n, band, drawheight, pix->samples, savealpha);
+ fz_write_pam_band(ctx, out, pix->w, totalheight, pix->n, pix->stride, band, drawheight, pix->samples, savealpha);
else if (output_format == OUT_PNG)
- fz_write_png_band(ctx, out, poc, pix->w, totalheight, pix->n, band, drawheight, pix->samples, savealpha);
+ fz_write_png_band(ctx, out, poc, pix->stride, band, drawheight, pix->samples);
else if (output_format == OUT_PWG)
fz_write_pixmap_as_pwg(ctx, out, pix, NULL);
else if (output_format == OUT_PCL)
@@ -905,10 +906,10 @@ static void dodrawpage(fz_context *ctx, fz_page *page, fz_display_list *list, in
fz_drop_bitmap(ctx, bit);
}
else
- fz_write_color_pcl_band(ctx, out, pccoc, pix->w, totalheight, pix->n, band, drawheight, pix->samples);
+ fz_write_color_pcl_band(ctx, out, pccoc, pix->w, totalheight, pix->n, pix->stride, band, drawheight, pix->samples);
}
else if (output_format == OUT_PS)
- fz_write_ps_band(ctx, out, psoc, pix->w, totalheight, pix->n, band, drawheight, pix->samples);
+ fz_write_ps_band(ctx, out, psoc, pix->w, totalheight, pix->n, pix->stride, band, drawheight, pix->samples);
else if (output_format == OUT_PBM) {
fz_bitmap *bit = fz_new_bitmap_from_pixmap_band(ctx, pix, NULL, band, bandheight);
fz_write_pbm_band(ctx, out, bit);
@@ -1537,20 +1538,24 @@ int mudraw_main(int argc, char **argv)
}
}
+ alpha = 1;
switch (out_cs)
{
case CS_MONO:
case CS_GRAY:
case CS_GRAY_ALPHA:
colorspace = fz_device_gray(ctx);
+ alpha = (out_cs == CS_GRAY_ALPHA);
break;
case CS_RGB:
case CS_RGB_ALPHA:
colorspace = fz_device_rgb(ctx);
+ alpha = (out_cs == CS_RGB_ALPHA);
break;
case CS_CMYK:
case CS_CMYK_ALPHA:
colorspace = fz_device_cmyk(ctx);
+ alpha = (out_cs == CS_CMYK_ALPHA);
break;
default:
fprintf(stderr, "Unknown colorspace!\n");
diff --git a/source/tools/murun.c b/source/tools/murun.c
index b8a7d991..e069bf0d 100644
--- a/source/tools/murun.c
+++ b/source/tools/murun.c
@@ -1748,10 +1748,11 @@ static void ffi_new_Pixmap(js_State *J)
fz_context *ctx = js_getcontext(J);
fz_colorspace *colorspace = js_touserdata(J, 1, "fz_colorspace");
fz_irect bounds = ffi_toirect(J, 2);
+ int alpha = js_toboolean(J, 3);
fz_pixmap *pixmap;
fz_try(ctx)
- pixmap = fz_new_pixmap_with_bbox(ctx, colorspace, &bounds);
+ pixmap = fz_new_pixmap_with_bbox(ctx, colorspace, &bounds, alpha);
fz_catch(ctx)
rethrow(J);
@@ -2260,11 +2261,11 @@ static void ffi_DisplayList_toPixmap(js_State *J)
fz_display_list *list = js_touserdata(J, 0, "fz_display_list");
fz_matrix ctm = ffi_tomatrix(J, 1);
fz_colorspace *colorspace = js_touserdata(J, 2, "fz_colorspace");
- int solid = js_isdefined(J, 3) ? js_toboolean(J, 3) : 1;
+ int alpha = js_isdefined(J, 3) ? js_toboolean(J, 3) : 0;
fz_pixmap *pixmap;
fz_try(ctx)
- pixmap = fz_new_pixmap_from_display_list(ctx, list, &ctm, colorspace, solid);
+ pixmap = fz_new_pixmap_from_display_list(ctx, list, &ctm, colorspace, alpha);
fz_catch(ctx)
rethrow(J);
@@ -3301,7 +3302,7 @@ int murun_main(int argc, char **argv)
jsB_propcon(J, "fz_buffer", "Buffer", ffi_new_Buffer, 1);
jsB_propcon(J, "fz_document", "Document", ffi_new_Document, 1);
- jsB_propcon(J, "fz_pixmap", "Pixmap", ffi_new_Pixmap, 2);
+ jsB_propcon(J, "fz_pixmap", "Pixmap", ffi_new_Pixmap, 3);
jsB_propcon(J, "fz_image", "Image", ffi_new_Image, 1);
jsB_propcon(J, "fz_font", "Font", ffi_new_Font, 2);
jsB_propcon(J, "fz_text", "Text", ffi_new_Text, 0);
diff --git a/source/tools/pdfextract.c b/source/tools/pdfextract.c
index 3f79137a..b784fda1 100644
--- a/source/tools/pdfextract.c
+++ b/source/tools/pdfextract.c
@@ -39,7 +39,7 @@ static void writepixmap(fz_context *ctx, fz_pixmap *pix, char *file, int rgb)
if (rgb && pix->colorspace && pix->colorspace != fz_device_rgb(ctx))
{
fz_irect bbox;
- converted = fz_new_pixmap_with_bbox(ctx, fz_device_rgb(ctx), fz_pixmap_bbox(ctx, pix, &bbox));
+ converted = fz_new_pixmap_with_bbox(ctx, fz_device_rgb(ctx), fz_pixmap_bbox(ctx, pix, &bbox), 1);
fz_convert_pixmap(ctx, converted, pix);
pix = converted;
}