From 8c349ca07417828579fba5088afd952daedc31c5 Mon Sep 17 00:00:00 2001 From: "pavlov@pavlov.net" Date: Thu, 22 Mar 2007 16:35:51 -0700 Subject: [PATCH] updating for APNG 0.10. splitting out render_op in to dispose_op and blend_op. bug 257197. r=asmith13, sr=vlad --- modules/libimg/png/png.h | 35 +++++++++------ modules/libimg/png/pngget.c | 24 +++++++--- modules/libimg/png/pngrutil.c | 14 +++--- modules/libimg/png/pngset.c | 45 ++++++++++--------- modules/libimg/png/pngwrite.c | 6 +-- modules/libimg/png/pngwutil.c | 11 ++--- modules/libpr0n/decoders/png/nsPNGDecoder.cpp | 12 ++--- 7 files changed, 88 insertions(+), 59 deletions(-) diff --git a/modules/libimg/png/png.h b/modules/libimg/png/png.h index 618ee88e0d54..225a55ea7b1c 100644 --- a/modules/libimg/png/png.h +++ b/modules/libimg/png/png.h @@ -909,7 +909,8 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) png_uint_32 next_frame_y_offset; png_uint_16 next_frame_delay_num; png_uint_16 next_frame_delay_den; - png_byte next_frame_render_op; + png_byte next_frame_dispose_op; + png_byte next_frame_blend_op; #endif } png_info; @@ -1411,11 +1412,14 @@ struct png_struct_def /* For png_struct.apng_flags: */ #define PNG_FIRST_FRAME_HIDDEN 0x0001 -/* dispose_op flags from render_op inside fcTL */ -#define PNG_RENDER_OP_DISPOSE_MASK 0x07 -#define PNG_RENDER_OP_DISPOSE_NONE 0x01 -#define PNG_RENDER_OP_DISPOSE_BACKGROUND 0x02 -#define PNG_RENDER_OP_DISPOSE_PREVIOUS 0x04 +/* dispose_op flags from inside fcTL */ +#define PNG_DISPOSE_OP_NONE 0x00 +#define PNG_DISPOSE_OP_BACKGROUND 0x01 +#define PNG_DISPOSE_OP_PREVIOUS 0x02 + +/* blend_op flags from inside fcTL */ +#define PNG_BLEND_OP_SOURCE 0x00 +#define PNG_BLEND_OP_OVER 0x01 /* This triggers a compiler error in png.c, if png.c and png.h * do not agree upon the version number. @@ -1740,8 +1744,8 @@ extern PNG_EXPORT (void,png_write_frame_head) PNGARG((png_structp png_ptr, png_infop png_info, png_bytepp row_pointers, png_uint_32 width, png_uint_32 height, png_uint_32 x_offset, png_uint_32 y_offset, - png_uint_16 delay_num, png_uint_16 delay_den, png_byte render_op, - png_byte first_frame_hidden)); + png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op, + png_byte blend_op, png_byte first_frame_hidden)); extern PNG_EXPORT (void,png_write_frame_tail) PNGARG((png_structp png_ptr, png_infop png_info)); @@ -2441,17 +2445,19 @@ extern PNG_EXPORT(png_uint_32,png_get_num_iterations) extern PNG_EXPORT(png_uint_32,png_get_next_frame_fcTL) PNGARG((png_structp png_ptr, png_infop info_ptr, png_uint_32 *width, png_uint_32 *height, png_uint_32 *x_offset, png_uint_32 *y_offset, - png_uint_16 *delay_num, png_uint_16 *delay_den, png_byte *render_op)); + png_uint_16 *delay_num, png_uint_16 *delay_den, png_byte *dispose_op, + png_byte *blend_op)); extern PNG_EXPORT(png_uint_32,png_set_next_frame_fcTL) PNGARG((png_structp png_ptr, png_infop info_ptr, png_uint_32 width, png_uint_32 height, png_uint_32 x_offset, png_uint_32 y_offset, - png_uint_16 delay_num, png_uint_16 delay_den, png_byte render_op)); + png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op, + png_byte blend_op)); extern PNG_EXPORT(void,png_ensure_fcTL_is_valid) PNGARG((png_structp png_ptr, png_uint_32 width, png_uint_32 height, png_uint_32 x_offset, png_uint_32 y_offset, png_uint_16 delay_num, png_uint_16 delay_den, - png_byte render_op)); + png_byte dispose_op, png_byte blend_op)); extern PNG_EXPORT(png_uint_32,png_get_next_frame_width) PNGARG((png_structp png_ptr, png_infop info_ptr)); extern PNG_EXPORT(png_uint_32,png_get_next_frame_height) @@ -2464,7 +2470,9 @@ extern PNG_EXPORT(png_uint_16,png_get_next_frame_delay_num) PNGARG((png_structp png_ptr, png_infop info_ptr)); extern PNG_EXPORT(png_uint_16,png_get_next_frame_delay_den) PNGARG((png_structp png_ptr, png_infop info_ptr)); -extern PNG_EXPORT(png_byte,png_get_next_frame_render_op) +extern PNG_EXPORT(png_byte,png_get_next_frame_dispose_op) + PNGARG((png_structp png_ptr, png_infop info_ptr)); +extern PNG_EXPORT(png_byte,png_get_next_frame_blend_op) PNGARG((png_structp png_ptr, png_infop info_ptr)); extern PNG_EXPORT(png_byte,png_first_frame_is_hidden) PNGARG((png_structp png_ptr, png_infop info_ptr)); @@ -3233,7 +3241,8 @@ PNG_EXTERN void png_write_acTL PNGARG((png_structp png_ptr, PNG_EXTERN void png_write_fcTL PNGARG((png_structp png_ptr, png_uint_32 width, png_uint_32 height, png_uint_32 x_offset, png_uint_32 y_offset, - png_uint_16 delay_num, png_uint_16 delay_den, png_byte render_op)); + png_uint_16 delay_num, png_uint_16 delay_den, + png_byte dispose_op, png_byte blend_op)); #endif /* Called when finished processing a row of data */ diff --git a/modules/libimg/png/pngget.c b/modules/libimg/png/pngget.c index 81b0087ee0ec..d2c528c03495 100644 --- a/modules/libimg/png/pngget.c +++ b/modules/libimg/png/pngget.c @@ -838,7 +838,7 @@ png_get_next_frame_fcTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 *width, png_uint_32 *height, png_uint_32 *x_offset, png_uint_32 *y_offset, png_uint_16 *delay_num, png_uint_16 *delay_den, - png_byte *render_op) + png_byte *dispose_op, png_byte *blend_op) { png_debug1(1, "in %s retrieval function\n", "fcTL"); @@ -846,7 +846,8 @@ png_get_next_frame_fcTL(png_structp png_ptr, png_infop info_ptr, (info_ptr->valid & PNG_INFO_fcTL) && width != NULL && height != NULL && x_offset != NULL && x_offset != NULL && - delay_num != NULL && delay_den != NULL && render_op != NULL) + delay_num != NULL && delay_den != NULL && + dispose_op != NULL && blend_op != NULL) { *width = info_ptr->next_frame_width; *height = info_ptr->next_frame_height; @@ -854,7 +855,8 @@ png_get_next_frame_fcTL(png_structp png_ptr, png_infop info_ptr, *y_offset = info_ptr->next_frame_y_offset; *delay_num = info_ptr->next_frame_delay_num; *delay_den = info_ptr->next_frame_delay_den; - *render_op = info_ptr->next_frame_render_op; + *dispose_op = info_ptr->next_frame_dispose_op; + *blend_op = info_ptr->next_frame_blend_op; return (1); } @@ -922,12 +924,22 @@ png_get_next_frame_delay_den(png_structp png_ptr, png_infop info_ptr) } png_byte PNGAPI -png_get_next_frame_render_op(png_structp png_ptr, png_infop info_ptr) +png_get_next_frame_dispose_op(png_structp png_ptr, png_infop info_ptr) { - png_debug(1, "in png_get_next_frame_render_op()\n"); + png_debug(1, "in png_get_next_frame_dispose_op()\n"); if (png_ptr != NULL && info_ptr != NULL) - return (info_ptr->next_frame_render_op); + return (info_ptr->next_frame_dispose_op); + return (0); +} + +png_byte PNGAPI +png_get_next_frame_blend_op(png_structp png_ptr, png_infop info_ptr) +{ + png_debug(1, "in png_get_next_frame_blend_op()\n"); + + if (png_ptr != NULL && info_ptr != NULL) + return (info_ptr->next_frame_blend_op); return (0); } diff --git a/modules/libimg/png/pngrutil.c b/modules/libimg/png/pngrutil.c index 7fd872e368b6..4f9f4e4c8213 100644 --- a/modules/libimg/png/pngrutil.c +++ b/modules/libimg/png/pngrutil.c @@ -2190,14 +2190,15 @@ png_handle_acTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) void /* PRIVATE */ png_handle_fcTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { - png_byte data[21]; + png_byte data[22]; png_uint_32 width; png_uint_32 height; png_uint_32 x_offset; png_uint_32 y_offset; png_uint_16 delay_num; png_uint_16 delay_den; - png_byte render_op; + png_byte dispose_op; + png_byte blend_op; png_debug(1, "in png_handle_fcTL\n"); @@ -2220,7 +2221,7 @@ png_handle_fcTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_crc_finish(png_ptr, length); return; } - else if (length != 25) + else if (length != 26) { png_warning(png_ptr, "fcTL with invalid length skipped"); png_crc_finish(png_ptr, length); @@ -2229,7 +2230,7 @@ png_handle_fcTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) png_ensure_sequence_number(png_ptr, length); - png_crc_read(png_ptr, data, 21); + png_crc_read(png_ptr, data, 22); png_crc_finish(png_ptr, 0); width = png_get_uint_31(png_ptr, data); @@ -2238,7 +2239,8 @@ png_handle_fcTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) y_offset = png_get_uint_31(png_ptr, data + 12); delay_num = png_get_uint_16(data + 16); delay_den = png_get_uint_16(data + 18); - render_op = data[20]; + dispose_op = data[20]; + blend_op = data[21]; if (png_ptr->num_frames_read == 0 && (x_offset != 0 || y_offset != 0)) png_error(png_ptr, "fcTL for the first frame must have zero offset"); @@ -2250,7 +2252,7 @@ png_handle_fcTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) /* the set function will do more error checking */ png_set_next_frame_fcTL(png_ptr, info_ptr, width, height, x_offset, y_offset, delay_num, delay_den, - render_op); + dispose_op, blend_op); png_read_reinit(png_ptr, info_ptr); diff --git a/modules/libimg/png/pngset.c b/modules/libimg/png/pngset.c index f47156fa7927..b75af7e18da3 100644 --- a/modules/libimg/png/pngset.c +++ b/modules/libimg/png/pngset.c @@ -1046,7 +1046,7 @@ png_set_next_frame_fcTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 width, png_uint_32 height, png_uint_32 x_offset, png_uint_32 y_offset, png_uint_16 delay_num, png_uint_16 delay_den, - png_byte render_op) + png_byte dispose_op, png_byte blend_op) { png_debug1(1, "in %s storage function\n", "fcTL"); @@ -1059,7 +1059,7 @@ png_set_next_frame_fcTL(png_structp png_ptr, png_infop info_ptr, } png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset, - delay_num, delay_den, render_op); + delay_num, delay_den, dispose_op, blend_op); info_ptr->next_frame_width = width; info_ptr->next_frame_height = height; @@ -1067,7 +1067,8 @@ png_set_next_frame_fcTL(png_structp png_ptr, png_infop info_ptr, info_ptr->next_frame_y_offset = y_offset; info_ptr->next_frame_delay_num = delay_num; info_ptr->next_frame_delay_den = delay_den; - info_ptr->next_frame_render_op = render_op; + info_ptr->next_frame_dispose_op = dispose_op; + info_ptr->next_frame_blend_op = blend_op; info_ptr->valid |= PNG_INFO_fcTL; @@ -1079,7 +1080,7 @@ png_ensure_fcTL_is_valid(png_structp png_ptr, png_uint_32 width, png_uint_32 height, png_uint_32 x_offset, png_uint_32 y_offset, png_uint_16 delay_num, png_uint_16 delay_den, - png_byte render_op) + png_byte dispose_op, png_byte blend_op) { if (width > png_ptr->first_frame_width || height > png_ptr->first_frame_height) @@ -1093,23 +1094,25 @@ png_ensure_fcTL_is_valid(png_structp png_ptr, png_error(png_ptr, "invalid x_offset in fcTL (> 2^31-1)"); if (y_offset > PNG_UINT_31_MAX) png_error(png_ptr, "invalid y_offset in fcTL (> 2^31-1)"); - if (render_op & 0xF0) - /* Bits 4 through 7 are reserved and must be set to zero (APNG spec) */ - png_error(png_ptr, "invalid render_op in fcTL"); - if (render_op & 0x08 && png_ptr->color_type == PNG_COLOR_TYPE_GRAY) - png_error(png_ptr, "APNG_RENDER_OP_BLEND_FLAG is not valid for " - "color type 'greyscale without alpha'"); - if ((render_op & 0x08) && - (png_ptr->color_type & PNG_COLOR_MASK_COLOR) && - !(png_ptr->color_type & PNG_COLOR_MASK_ALPHA)) - png_error(png_ptr, "APNG_RENDER_OP_BLEND_FLAG is not valid for " - "color type 'truecolor without alpha'"); - if (!(render_op & PNG_RENDER_OP_DISPOSE_MASK)) - png_error(png_ptr, "no DISPOSE_ flag found in fcTL"); - if ( (render_op & PNG_RENDER_OP_DISPOSE_MASK) != PNG_RENDER_OP_DISPOSE_NONE && - (render_op & PNG_RENDER_OP_DISPOSE_MASK) != PNG_RENDER_OP_DISPOSE_BACKGROUND && - (render_op & PNG_RENDER_OP_DISPOSE_MASK) != PNG_RENDER_OP_DISPOSE_PREVIOUS) - png_error(png_ptr, "multiple DISPOSE_ flags set in fcTL"); + + if (dispose_op != PNG_DISPOSE_OP_NONE && + dispose_op != PNG_DISPOSE_OP_BACKGROUND && + dispose_op != PNG_DISPOSE_OP_PREVIOUS) + png_error(png_ptr, "invalid dispose_op in fcTL"); + + if (blend_op != PNG_BLEND_OP_SOURCE && + blend_op != PNG_BLEND_OP_OVER) + png_error(png_ptr, "invalid blend_op in fcTL"); + + if (blend_op == PNG_BLEND_OP_OVER) { + if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + png_error(png_ptr, "PNG_BLEND_OP_OVER is not valid for " + "color type 'greyscale without alpha'"); + else if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) && + !(png_ptr->color_type & PNG_COLOR_MASK_ALPHA)) + png_error(png_ptr, "PNG_BLEND_OP_OVER is not valid for " + "color type 'truecolor without alpha'"); + } } #endif /* PNG_APNG_SUPPORTED */ diff --git a/modules/libimg/png/pngwrite.c b/modules/libimg/png/pngwrite.c index 9ac7ec8ffc81..70e1d1a052cc 100644 --- a/modules/libimg/png/pngwrite.c +++ b/modules/libimg/png/pngwrite.c @@ -1524,8 +1524,8 @@ void PNGAPI png_write_frame_head(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers, png_uint_32 width, png_uint_32 height, png_uint_32 x_offset, png_uint_32 y_offset, - png_uint_16 delay_num, png_uint_16 delay_den, png_byte render_op, - png_byte first_frame_hidden) + png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op, + png_byte blend_op, png_byte first_frame_hidden) { png_debug(1, "in png_write_frame_head\n"); @@ -1540,7 +1540,7 @@ png_write_frame_head(png_structp png_ptr, png_infop info_ptr, if ( !(png_ptr->num_frames_written == 0 && first_frame_hidden) ) png_write_fcTL(png_ptr, width, height, x_offset, y_offset, - delay_num, delay_den, render_op); + delay_num, delay_den, dispose_op, blend_op); } void PNGAPI diff --git a/modules/libimg/png/pngwutil.c b/modules/libimg/png/pngwutil.c index 378ed44c3b0b..3fed916c62b1 100644 --- a/modules/libimg/png/pngwutil.c +++ b/modules/libimg/png/pngwutil.c @@ -1754,12 +1754,12 @@ png_write_acTL(png_structp png_ptr, void /* PRIVATE */ png_write_fcTL(png_structp png_ptr, png_uint_32 width, png_uint_32 height, png_uint_32 x_offset, png_uint_32 y_offset, - png_uint_16 delay_num, png_uint_16 delay_den, png_byte render_op) + png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op, png_byte blend_op) { #ifdef PNG_USE_LOCAL_ARRAYS PNG_fcTL; #endif - png_byte data[25]; + png_byte data[26]; png_debug(1, "in png_write_fcTL\n"); @@ -1773,7 +1773,7 @@ png_write_fcTL(png_structp png_ptr, png_uint_32 width, png_uint_32 height, /* more error checking */ png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset, - delay_num, delay_den, render_op); + delay_num, delay_den, dispose_op, blend_op); png_save_uint_32(data, png_ptr->next_seq_num); png_save_uint_32(data + 4, width); @@ -1782,9 +1782,10 @@ png_write_fcTL(png_structp png_ptr, png_uint_32 width, png_uint_32 height, png_save_uint_32(data + 16, y_offset); png_save_uint_16(data + 20, delay_num); png_save_uint_16(data + 22, delay_den); - data[24] = render_op; + data[24] = dispose_op; + data[25] = blend_op; - png_write_chunk(png_ptr, (png_bytep)png_fcTL, data, (png_size_t)25); + png_write_chunk(png_ptr, (png_bytep)png_fcTL, data, (png_size_t)26); png_ptr->next_seq_num++; } diff --git a/modules/libpr0n/decoders/png/nsPNGDecoder.cpp b/modules/libpr0n/decoders/png/nsPNGDecoder.cpp index 685c3ba8a404..5084872ed1e9 100644 --- a/modules/libpr0n/decoders/png/nsPNGDecoder.cpp +++ b/modules/libpr0n/decoders/png/nsPNGDecoder.cpp @@ -114,13 +114,15 @@ void nsPNGDecoder::CreateFrame(png_uint_32 x_offset, png_uint_32 y_offset, void nsPNGDecoder::SetAnimFrameInfo() { png_uint_16 delay_num, delay_den; /* in seconds */ - png_byte render_op; + png_byte dispose_op; PRInt32 timeout; /* in milliseconds */ delay_num = png_get_next_frame_delay_num(mPNG, mInfo); delay_den = png_get_next_frame_delay_den(mPNG, mInfo); - render_op = png_get_next_frame_render_op(mPNG, mInfo); - + dispose_op = png_get_next_frame_dispose_op(mPNG, mInfo); + + // XXX need to handle blend_op here! + if (delay_num == 0) { timeout = 0; // gfxImageFrame::SetTimeout() will set to a minimum } else { @@ -134,9 +136,9 @@ void nsPNGDecoder::SetAnimFrameInfo() } mFrame->SetTimeout(timeout); - if (render_op & PNG_RENDER_OP_DISPOSE_PREVIOUS) + if (dispose_op == PNG_DISPOSE_OP_PREVIOUS) mFrame->SetFrameDisposalMethod(imgIContainer::kDisposeRestorePrevious); - else if (render_op & PNG_RENDER_OP_DISPOSE_BACKGROUND) + else if (dispose_op == PNG_DISPOSE_OP_BACKGROUND) mFrame->SetFrameDisposalMethod(imgIContainer::kDisposeClear); else mFrame->SetFrameDisposalMethod(imgIContainer::kDisposeKeep);