diff options
author | Oswald Buddenhagen <oswald.buddenhagen@nokia.com> | 2011-08-18 09:01:28 (GMT) |
---|---|---|
committer | Oswald Buddenhagen <oswald.buddenhagen@nokia.com> | 2011-08-18 09:01:28 (GMT) |
commit | d9b8c530fceced62ab620307f399c3e985640282 (patch) | |
tree | b53c8043d7c244437ec8655f4186e26f34ce7a5b | |
parent | 182b10dbad23e9da310c0d600095f17c41dd0d3c (diff) | |
parent | 5e435bfcad5a05c775c9d45edbd2659c87416754 (diff) | |
download | Qt-d9b8c530fceced62ab620307f399c3e985640282.zip Qt-d9b8c530fceced62ab620307f399c3e985640282.tar.gz Qt-d9b8c530fceced62ab620307f399c3e985640282.tar.bz2 |
Merge remote-tracking branch 'mainline/4.8'
63 files changed, 17812 insertions, 3025 deletions
diff --git a/examples/webkit/fancybrowser/fancybrowser.pro b/examples/webkit/fancybrowser/fancybrowser.pro index 1ed212e..9d3d27e 100644 --- a/examples/webkit/fancybrowser/fancybrowser.pro +++ b/examples/webkit/fancybrowser/fancybrowser.pro @@ -12,8 +12,8 @@ INSTALLS += target sources symbian { TARGET.UID3 = 0xA000CF6C - TARGET.EPOCHEAPSIZE = 0020000 04000000 - TARGET.CAPABILITY += NetworkServices + TARGET.EPOCHEAPSIZE = 0x1000 0x8000000 + TARGET.CAPABILITY += Location NetworkServices include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri) } maemo5: include($$QT_SOURCE_TREE/examples/maemo5pkgrules.pri) diff --git a/mkspecs/common/symbian/symbian.conf b/mkspecs/common/symbian/symbian.conf index 4025c54..b19eece 100644 --- a/mkspecs/common/symbian/symbian.conf +++ b/mkspecs/common/symbian/symbian.conf @@ -84,7 +84,11 @@ QMAKE_LIBS_OPENGL_ES2_QT = $$QMAKE_LIBS_OPENGL_ES2 $$QMAKE_LIBS_CFBSBITMAP -lcon QMAKE_LIBS_OPENVG = $$QMAKE_LIBS_CFBSBITMAP -llibOpenVG QMAKE_LIBS_THREAD = -llibpthread QMAKE_LIBS_COMPAT = -QMAKE_LIBS_S60 = -lavkon -leikcoctl -lgfxtrans +QMAKE_LIBS_S60 = -lavkon -leikcoctl + +exists($${EPOCROOT}epoc32/include/platform/mw/akntranseffect.h) { + QMAKE_LIBS_S60 += -lgfxtrans +} exists($${EPOCROOT}epoc32/include/platform/sgresource/sgimage.h) { QMAKE_LIBS_OPENVG += -lsgresource diff --git a/mkspecs/symbian-gcce/qmake.conf b/mkspecs/symbian-gcce/qmake.conf index 17b1c5f..b252a9c 100644 --- a/mkspecs/symbian-gcce/qmake.conf +++ b/mkspecs/symbian-gcce/qmake.conf @@ -56,7 +56,7 @@ QMAKE_LFLAGS_APP += --entry=_E32Startup -u _E32Startup QMAKE_LFLAGS_SHLIB += -shared --default-symver --entry=_E32Dll -u _E32Dll QMAKE_LFLAGS_PLUGIN += $$QMAKE_LFLAGS_SHLIB -gcceExtraFlags = --include=$${EPOCROOT}epoc32/include/gcce/gcce.h -march=armv5t -mapcs -mthumb-interwork -nostdinc -c -msoft-float -T script +gcceExtraFlags = --include=$${EPOCROOT}epoc32/include/gcce/gcce.h -march=armv5t -mapcs -mthumb-interwork -nostdinc -c -msoft-float QMAKE_CFLAGS += $${gcceExtraFlags} QMAKE_CXXFLAGS += $${gcceExtraFlags} -x c++ -fexceptions -fno-unit-at-a-time -fvisibility-inlines-hidden -Os #If we are not going to link to Qt or qtmain.lib, we need to include this at least once. diff --git a/qmake/generators/symbian/symbiancommon.cpp b/qmake/generators/symbian/symbiancommon.cpp index a0a8eea..d4db4b9 100644 --- a/qmake/generators/symbian/symbiancommon.cpp +++ b/qmake/generators/symbian/symbiancommon.cpp @@ -993,7 +993,12 @@ bool SymbianCommonGenerator::parseTsContent(const QString &tsFilename, SymbianLo if (xml.name() == sourceElement) { source = xml.readElementText(); } else if (xml.name() == translationElement) { - translation = xml.readElementText(); + // Technically translation element can have child elements + // i.e. numerusform and lengthvariant. We don't support + // these for actual caption/pkgname translations, but since + // they may be present on other unrelated message elements, + // we need to explicitly skip them to avoid parsing errors. + translation = xml.readElementText(QXmlStreamReader::SkipChildElements); } else { xml.skipCurrentElement(); } diff --git a/src/3rdparty/libpng/ANNOUNCE b/src/3rdparty/libpng/ANNOUNCE index 4a3b018..2a9fb65 100644 --- a/src/3rdparty/libpng/ANNOUNCE +++ b/src/3rdparty/libpng/ANNOUNCE @@ -1,5 +1,5 @@ -Libpng 1.5.1 - February 3, 2011 +Libpng 1.5.4 - July 7, 2011 This is a public release of libpng, intended for use in production codes. @@ -8,85 +8,184 @@ Files available for download: Source files with LF line endings (for Unix/Linux) and with a "configure" script - libpng-1.5.1.tar.xz (LZMA-compressed, recommended) - libpng-1.5.1.tar.gz - libpng-1.5.1.tar.bz2 + libpng-1.5.4.tar.xz (LZMA-compressed, recommended) + libpng-1.5.4.tar.gz + libpng-1.5.4.tar.bz2 Source files with CRLF line endings (for Windows), without the "configure" script - lpng151.7z (LZMA-compressed, recommended) - lpng151.zip + lpng154.7z (LZMA-compressed, recommended) + lpng154.zip Other information: - libpng-1.5.1-README.txt - libpng-1.5.1-LICENSE.txt + libpng-1.5.4-README.txt + libpng-1.5.4-LICENSE.txt -Changes since the last public release (1.5.0): +Changes since the last public release (1.5.2): - Added description of png_set_crc_action() to the manual. - Added a note in the manual that the type of the iCCP profile was changed - from png_charpp to png_bytepp in png_get_iCCP(). Similarly, - it was changed from png_charpp to png_const_bytepp in png_set_iCCP(). - Ensure that png_rgb_to_gray ignores palette mapped images, if libpng - internally happens to call it with one. - Fixed the failure to handle palette mapped images correctly. - Fixed a bug in handling of interlaced images (bero at arklinux.org). - Updated CMakeLists.txt (Clifford Yapp) - Fixed typecasting of some png_debug() statements (Cosmin) - Updated documentation of png_set|get_tRNS() (Thomas Klausner). - Mentioned in the documentation that applications must #include "zlib.h" - if they need access to anything in zlib.h, and that a number of - macros such as png_memset() are no longer accessible by applications. - Corrected pngvalid gamma test "sample" function to access all of the color - samples of each pixel, instead of sampling the red channel three times. - Changed variable names index, div, exp, and gamma to char_index, divisor, - exp_b10, and gamma_val, respectively, to avoid "shadow" warnings. - Prevent png_push_crc_skip() from hanging while reading an unknown chunk - or an over-large compressed zTXt chunk with the progressive reader. - Eliminated more GCC "shadow" warnings. - Revised png_fixed() in png.c to avoid compiler warning about reaching the - end without returning anything. - In the manual, describe the png_get_IHDR() arguments in the correct order. - Added const_png_structp and const_png_infop types, and used them in - prototypes for most png_get_*() functions. - Added png_get_io_chunk_type() and deprecated png_get_io_chunk_name() - Added synopses for the IO_STATE functions and other missing synopses - to the manual. Removed the synopses from libpngpf.3 because they - were out of date and no longer useful. Better information can be - obtained by reading the prototypes and comments in pngpriv.h - Attempted to fix cpp on Solaris with S. Studio 12 cc, fix build - Added a make macro DFNCPP that is a CPP that will accept the tokens in - a .dfn file and adds configure stuff to test for such a CPP. ./configure - should fail if one is not available. - Corrected const_png_ in png.h to png_const_ to avoid polluting the namespace. - Added png_get_current_row_number and png_get_current_pass_number for the - benefit of the user transform callback. - Added png_process_data_pause and png_process_data_skip for the benefit of - progressive readers that need to stop data processing or want to optimize - skipping of unread data (e.g. if the reader marks a chunk to be skipped.) - Enhanced pngvalid, corrected an error in gray_to_rgb, corrected doc error. - pngvalid contains tests of transforms, which tests are currently disabled - because they are incompletely tested. gray_to_rgb was failing to expand - the bit depth for smaller bit depth images; this seems to be a long - standing error and resulted, apparently, in invalid output. The - documentation did not accurately describe what libpng really does when - converting RGB to gray. - Fixed incorrect examples of callback prototypes in the manual, that were - introduced in libpng-1.0.0. - In addition the order of the png_get_uint macros with respect to the - relevant function definitions has been reversed. This helps the - preprocessing of the symbol files be more robust. Furthermore, the - symbol file preprocessing now uses -DPNG_NO_USE_READ_MACROS even when - the library may actually be built with PNG_USE_READ_MACROS; this stops - the read macros interfering with the symbol file format. - Made the manual, synopses, and function prototypes use the function - argument names file_gamma, int_file_gamma, and srgb_intent consistently. - Changed PNG_UNUSED from "param=param;" to "(void)param;". - Added transform tests to pngvalid and simplified the arguments. - Added a request in the manual that applications do not use "png_" or - "PNG_" to begin any of their own symbols. + Re-initialize the zlib compressor before compressing non-IDAT chunks. + Added API functions to set parameters for zlib compression of non-IDAT + chunks. + Updated scripts/symbols.def with new API functions. + Only compile the new zlib re-initializing code when text or iCCP is + supported, using PNG_WRITE_COMPRESSED_TEXT_SUPPORTED macro. + Improved the optimization of the zlib CMF byte (see libpng-1.2.6). + Optimize the zlib CMF byte in non-IDAT compressed chunks + Fixed gcc -ansi -pedantic compile. A strict ANSI system does not have + snprintf, and the "__STRICT_ANSI__" detects that condition more reliably + than __STDC__ (John Bowler). + Removed the PNG_PTR_NORETURN attribute because it too dangerous. It tells + the compiler that a user supplied callback (the error handler) does not + return, yet there is no guarantee in practice that the application code + will correctly implement the error handler because the compiler only + issues a warning if there is a mistake (John Bowler). + Removed the no-longer-used PNG_DEPSTRUCT macro. + Updated the zlib version to 1.2.5 in the VStudio project. + Fixed 64-bit builds where png_uint_32 is smaller than png_size_t in + pngwutil.c (John Bowler). + Fixed bug with stripping the filler or alpha channel when writing, that + was introduced in libpng-1.5.2 (bug report by Andrew Church). + Updated pngtest.png with the new zlib CMF optimization. + Cleaned up conditional compilation code and of background/gamma handling + Internal changes only except a new option to avoid compiling the + png_build_grayscale_palette API (which is not used at all internally.) + The main change is to move the transform tests (READ_TRANSFORMS, + WRITE_TRANSFORMS) up one level to the caller of the APIs. This avoids + calls to spurious functions if all transforms are disabled and slightly + simplifies those functions. Pngvalid modified to handle this. + A minor change is to stop the strip_16 and expand_16 interfaces from + disabling each other; this allows the future alpha premultiplication + code to use 16-bit intermediate values while still producing 8-bit output. + png_do_background and png_do_gamma have been simplified to take a single + pointer to the png_struct rather than pointers to every item required + from the png_struct. This makes no practical difference to the internal + code. + A serious bug in the pngvalid internal routine 'standard_display_init' has + been fixed - this failed to initialize the red channel and accidentally + initialized the alpha channel twice. + Changed png_struct jmp_buf member name from png_jmpbuf to tmp_jmpbuf to + avoid a clash with the png_jmpbuf macro on some platforms. + Added appropriate feature test macros to ensure libpng sees the correct API + _POSIX_SOURCE is defined in pngpriv.h, pngtest.c and pngvalid.c to ensure + that POSIX conformant systems disable non-POSIX APIs. _ISOC99_SOURCE is + defined in pngpriv.h to obtain the ISO C99 snprintf definition, when + available. + Removed png_snprintf and added formatted warning messages. This change adds + internal APIs to allow png_warning messages to have parameters without + requiring the host OS to implement snprintf. As a side effect the + dependency of the tIME-supporting RFC1132 code on stdio is removed and + PNG_NO_WARNINGS does actually work now. + Added PNG_WRITE_OPTIMIZE_CMF_SUPPORTED macro to make the zlib "CMF" byte + optimization configureable. + Internal functions were added to claim/release the z_stream and, hopefully, + make the code more robust. Also deflateEnd checking is added - previously + libpng would ignore an error at the end of the stream. + Removed the -D_ALL_SOURCE from definitions for AIX in CMakeLists.txt + Implemented premultiplied alpha support: png_set_alpha_mode API + Added expand_16 support to the high level interface. + Added named value and 'flag' gamma support to png_set_gamma. Made a minor + change from the previous (unreleased) ABI/API to hide the exact value used + for Macs - it's not a good idea to embed this in the ABI! + Moved macro definitions for PNG_HAVE_IHDR, PNG_HAVE_PLTE, and PNG_AFTER_IDAT + from pngpriv.h to png.h because they must be visible to applications + that call png_set_unknown_chunks(). + Check for up->location !PNG_AFTER_IDAT when writing unknown chunks + before IDAT. + Improved "pngvalid --speed" to exclude more of pngvalid from the time. + Documented png_set_alpha_mode(), other changes in libpng.3/libpng-manual.txt + The cHRM chunk now sets the defaults for png_set_rgb_to_gray() (when negative + parameters are supplied by the caller), while in the absence of cHRM + sRGB/Rec 709 values are still used. + The bKGD chunk no longer overwrites the background value set by + png_set_background(), allowing the latter to be used before the file + header is read. It never performed any useful function to override + the default anyway. + Added memory overwrite and palette image checks to pngvalid.c + Previously palette image code was poorly checked. Since the transformation + code has a special palette path in most cases this was a severe weakness. + Minor cleanup and some extra checking in pngrutil.c and pngrtran.c. When + expanding an indexed image, always expand to RGBA if transparency is + present. + Reversed earlier 1.5.3 change of transformation order; move png_expand_16 + back where it was. The change doesn't work because it requires 16-bit + gamma tables when the code only generates 8-bit ones. This fails + silently; the libpng code just doesn't do any gamma correction. Moving + the tests back leaves the old, inaccurate, 8-bit gamma calculations, but + these are clearly better than none! + png_set_background() and png_expand_16() did not work together correctly. + This problem is present in 1.5.2; if png_set_background is called with + need_expand false and the matching 16 bit color libpng erroneously just + treats it as an 8-bit color because of where png_do_expand_16 is in the + transform list. This simple fix reduces the supplied colour to 8-bits, + so it gets smashed, but this is better than the current behavior. + Added tests for expand16, more fixes for palette image tests to pngvalid. + Corrects the code for palette image tests and disables attempts to + validate palette colors. + Fixed uninitialized memory read in png_format_buffer() (Bug report by + Frank Busse, related to CVE-2004-0421). + Fixed png_handle_sCAL which is broken in 1.5; added sCAL to pngtest.png + Revised documentation about png_set_user_limits() to say that it also affects + png writing. + Revised handling of png_set_user_limits() so that it can increase the + limit beyond the PNG_USER_WIDTH|HEIGHT_MAX; previously it could only + reduce it. + Make the 16-to-8 scaling accurate. Dividing by 256 with no rounding is + wrong (high by one) 25% of the time. Dividing by 257 with rounding is + wrong in 128 out of 65536 cases. Getting the right answer all the time + without division is easy. + Added "_SUPPORTED" to the PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION macro. + Added projects/owatcom, an IDE project for OpenWatcom to replace + scripts/makefile.watcom. This project works with OpenWatcom 1.9. The + IDE autogenerates appropriate makefiles (libpng.mk) for batch processing. + The project is configurable, unlike the Visual Studio project, so long + as the developer has an awk. + Changed png_set_gAMA to limit the gamma value range so that the inverse + of the stored value cannot overflow the fixed point representation, + and changed other things OpenWatcom warns about. + Revised pngvalid.c to test PNG_ALPHA_MODE_SUPPORTED correctly. This allows + pngvalid to build when ALPHA_MODE is not supported, which is required if + it is to build on libpng 1.4. + Removed string/memory macros that are no longer used and are not + necessarily fully supportable, particularly png_strncpy and png_snprintf. + Added log option to pngvalid.c and attempted to improve gamma messages. + People found the presence of a beta release following an rc release + to be confusing; therefore we bump the version to libpng-1.5.4beta01 + and there will be no libpng-1.5.3 release. + Moved definitions of PNG_HAVE_IHDR, PNG_AFTER_IDAT, and PNG_HAVE_PLTE + outside of an unknown-chunk block in png.h because they are also + needed for other uses. + Added png_set_scale_16() API, to match inaccurate results from previous + libpng versions, configurable with PNG_READ_SCALE_16_TO_8_SUPPORTED. + Fixed a problem in png_do_expand_palette() exposed by optimization in + 1.5.3beta06 + Also removed a spurious and confusing "trans" member ("trans") from png_info. + The palette expand optimization prevented expansion to an intermediate RGBA + form if tRNS was present but alpha was marked to be stripped; this exposed + a check for tRNS in png_do_expand_palette() which is inconsistent with the + code elsewhere in libpng. + Added PNG_TRANSFORM_SCALE_16 to the high-level read transforms. + If PNG_READ_16_TO_8_ACCURATE_SCALE is not enabled, png_set_scale_16() + and png_do_scale_16_to_8() aren't built. + Revised contrib/visupng, gregbook, and pngminim to demonstrate scale_16_to_8 + Fixed pngvalid, simplified macros, added checking for 0 in sCAL. + The ACCURATE scale macro is no longer defined in libpng-1.5 - call the + png_scale_16_to_8 API. Made sure that PNG_READ_16_TO_8 is still defined + if the png_strip_16_to_8 API is present. png_check_fp_number now + maintains some state so that positive, negative and zero values are + identified. sCAL uses these to be strictly spec conformant. + Define PNG_ALLOCATED to "restrict" only if MSC_VER >= 1400. + +Send comments/corrections/commendations to png-mng-implement at lists.sf.net +(subscription required; visit +https://lists.sourceforge.net/lists/listinfo/png-mng-implement +to subscribe) +or to glennrp at users.sourceforge.net + +Glenn R-P +*/ } +#endif Send comments/corrections/commendations to png-mng-implement at lists.sf.net (subscription required; visit diff --git a/src/3rdparty/libpng/CHANGES b/src/3rdparty/libpng/CHANGES index fa5f2aa..628d7f0 100644 --- a/src/3rdparty/libpng/CHANGES +++ b/src/3rdparty/libpng/CHANGES @@ -15,7 +15,7 @@ Version 0.3 fixed some bugs in writer interfaced with zlib 0.5 added K&R support - added check for 64 KB blocks for 16 bit machines + added check for 64 KB blocks for 16-bit machines Version 0.4 cleaned up code and commented code @@ -74,7 +74,7 @@ Version 0.82 [September, 1995] Version 0.85 [December, 1995] added more medium model code (almost everything's a far) added i/o, error, and memory callback functions - fixed some bugs (16 bit, 4 bit interlaced, etc.) + fixed some bugs (16-bit, 4-bit interlaced, etc.) added first run progressive reader (barely tested) Version 0.86 [January, 1996] @@ -2935,7 +2935,7 @@ Version 1.5.0beta36 [July 29, 2010] PNG_INTERLACE transform and to get the number of rows in the current pass. A new test program, pngvalid.c, validates the gamma code. - Errors in the 16 bit gamma correction (overflows) have been corrected. + Errors in the 16-bit gamma correction (overflows) have been corrected. cHRM chunk testing is done consistently (previously the floating point API bypassed it, because the test really didn't work on FP, now the test is performed on the actual values to be stored in the PNG file so it @@ -3208,9 +3208,9 @@ Version 1.5.1beta09 [January 24, 2011] pngvalid contains tests of transforms, which tests are currently disabled because they are incompletely tested. gray_to_rgb was failing to expand the bit depth for smaller bit depth images; this seems to be a long - standing error and resulted, apparently, in invalid output. The - documentation did not accurately describe what libpng really does when - converting RGB to gray. + standing error and resulted, apparently, in invalid output + (CVE-2011-0408, CERT VU#643140). The documentation did not accurately + describe what libpng really does when converting RGB to gray. Version 1.5.1beta10 [January 27, 2010] Fixed incorrect examples of callback prototypes in the manual, that were @@ -3227,7 +3227,7 @@ Version 1.5.1beta10 [January 27, 2010] Version 1.5.1beta11 [January 28, 2011] Changed PNG_UNUSED from "param=param;" to "{if(param){}}". Corrected local variable type in new API png_process_data_skip() - The type was self-evidently incorrect but only causes problems on 64 bit + The type was self-evidently incorrect but only causes problems on 64-bit architectures. Added transform tests to pngvalid and simplified the arguments. @@ -3242,6 +3242,272 @@ Version 1.5.1rc02 [January 31, 2011] Version 1.5.1 [February 3, 2011] No changes. +Version 1.5.2beta01 [February 13, 2011] + More -Wshadow fixes for older gcc compilers. Older gcc versions apparently + check formal parameters names in function declarations (as well as + definitions) to see if they match a name in the global namespace. + Revised PNG_EXPORTA macro to not use an empty parameter, to accommodate the + old VisualC++ preprocessor. + Turned on interlace handling in png_read_png(). + Fixed gcc pendantic warnings. + Handle longjmp in Cygwin. + Fixed png_get_current_row_number() in the interlaced case. + Cleaned up ALPHA flags and transformations. + Implemented expansion to 16 bits. + +Version 1.5.2beta02 [February 19, 2011] + Fixed mistake in the descriptions of user read_transform and write_transform + function prototypes in the manual. The row_info struct is png_row_infop. + Reverted png_get_current_row_number() to previous (1.5.2beta01) behavior. + Corrected png_get_current_row_number documentation + Fixed the read/write row callback documentation. + This documents the current behavior, where the callback is called after + every row with information pertaining to the next row. + +Version 1.5.2beta03 [March 3, 2011] + Fixed scripts/makefile.vcwin32 + Updated contrib/pngsuite/README to add the word "modify". + Define PNG_ALLOCATED to blank when _MSC_VER<1300. + +Version 1.5.2rc01 [March 19, 2011] + Define remaining attributes to blank when MSC_VER<1300. + ifdef out mask arrays in pngread.c when interlacing is not supported. + +Version 1.5.2rc02 [March 22, 2011] + Added a hint to try CPP=/bin/cpp if "cpp -E" fails in scripts/pnglibconf.mak + and in contrib/pngminim/*/makefile, eg., on SunOS 5.10, and removed "strip" + from the makefiles. + Fixed a bug (present since libpng-1.0.7) that makes png_handle_sPLT() fail + to compile when PNG_NO_POINTER_INDEXING is defined (Chubanov Kirill) + +Version 1.5.2rc03 [March 24, 2011] + Don't include standard header files in png.h while building the symbol table, + to avoid cpp failure on SunOS (introduced PNG_BUILDING_SYMBOL_TABLE macro). + +Version 1.5.2 [March 31, 2011] + No changes. + +Version 1.5.3beta01 [April 1, 2011] + Re-initialize the zlib compressor before compressing non-IDAT chunks. + Added API functions to set parameters for zlib compression of non-IDAT + chunks. + +Version 1.5.3beta02 [April 3, 2011] + Updated scripts/symbols.def with new API functions. + Only compile the new zlib re-initializing code when text or iCCP is + supported, using PNG_WRITE_COMPRESSED_TEXT_SUPPORTED macro. + Improved the optimization of the zlib CMF byte (see libpng-1.2.6beta03). + Optimize the zlib CMF byte in non-IDAT compressed chunks + +Version 1.5.3beta03 [April 16, 2011] + Fixed gcc -ansi -pedantic compile. A strict ANSI system does not have + snprintf, and the "__STRICT_ANSI__" detects that condition more reliably + than __STDC__ (John Bowler). + Removed the PNG_PTR_NORETURN attribute because it too dangerous. It tells + the compiler that a user supplied callback (the error handler) does not + return, yet there is no guarantee in practice that the application code + will correctly implement the error handler because the compiler only + issues a warning if there is a mistake (John Bowler). + Removed the no-longer-used PNG_DEPSTRUCT macro. + Updated the zlib version to 1.2.5 in the VStudio project. + Fixed 64-bit builds where png_uint_32 is smaller than png_size_t in + pngwutil.c (John Bowler). + Fixed bug with stripping the filler or alpha channel when writing, that + was introduced in libpng-1.5.2beta01 (bug report by Andrew Church). + +Version 1.5.3beta04 [April 27, 2011] + Updated pngtest.png with the new zlib CMF optimization. + Cleaned up conditional compilation code and of background/gamma handling + Internal changes only except a new option to avoid compiling the + png_build_grayscale_palette API (which is not used at all internally.) + The main change is to move the transform tests (READ_TRANSFORMS, + WRITE_TRANSFORMS) up one level to the caller of the APIs. This avoids + calls to spurious functions if all transforms are disabled and slightly + simplifies those functions. Pngvalid modified to handle this. + A minor change is to stop the strip_16 and expand_16 interfaces from + disabling each other; this allows the future alpha premultiplication + code to use 16-bit intermediate values while still producing 8-bit output. + png_do_background and png_do_gamma have been simplified to take a single + pointer to the png_struct rather than pointers to every item required + from the png_struct. This makes no practical difference to the internal + code. + A serious bug in the pngvalid internal routine 'standard_display_init' has + been fixed - this failed to initialize the red channel and accidentally + initialized the alpha channel twice. + Changed png_struct jmp_buf member name from png_jmpbuf to tmp_jmpbuf to + avoid a possible clash with the png_jmpbuf macro on some platforms. + +Version 1.5.3beta05 [May 6, 2011] + Added the "_POSIX_SOURCE" feature test macro to ensure libpng sees the + correct API. _POSIX_SOURCE is defined in pngpriv.h, pngtest.c and + pngvalid.c to ensure that POSIX conformant systems disable non-POSIX APIs. + Removed png_snprintf and added formatted warning messages. This change adds + internal APIs to allow png_warning messages to have parameters without + requiring the host OS to implement snprintf. As a side effect the + dependency of the tIME-supporting RFC1132 code on stdio is removed and + PNG_NO_WARNINGS does actually work now. + Pass "" instead of '\0' to png_default_error() in png_err(). This mistake + was introduced in libpng-1.2.20beta01. + Added PNG_WRITE_OPTIMIZE_CMF_SUPPORTED macro to make the zlib "CMF" byte + optimization configureable. + IDAT compression failed if preceded by a compressed text chunk (bug + introduced in libpng-1.5.3beta01-02). This was because the attempt to + reset the zlib stream in png_write_IDAT happened after the first IDAT + chunk had been deflated - much too late. In this change internal + functions were added to claim/release the z_stream and, hopefully, make + the code more robust. Also deflateEnd checking is added - previously + libpng would ignore an error at the end of the stream. + +Version 1.5.3beta06 [May 8, 2011] + Removed the -D_ALL_SOURCE from definitions for AIX in CMakeLists.txt + Implemented premultiplied alpha support: png_set_alpha_mode API + +Version 1.5.3beta07 [May 11, 2011] + Added expand_16 support to the high level interface. + Added named value and 'flag' gamma support to png_set_gamma. Made a minor + change from the previous (unreleased) ABI/API to hide the exact value used + for Macs - it's not a good idea to embed this in the ABI! + Moved macro definitions for PNG_HAVE_IHDR, PNG_HAVE_PLTE, and PNG_AFTER_IDAT + from pngpriv.h to png.h because they must be visible to applications + that call png_set_unknown_chunks(). + Check for up->location !PNG_AFTER_IDAT when writing unknown chunks + before IDAT. + +Version 1.5.3beta08 [May 16, 2011] + Improved "pngvalid --speed" to exclude more of pngvalid from the time. + Documented png_set_alpha_mode(), other changes in libpng.3/libpng-manual.txt + The cHRM chunk now sets the defaults for png_set_rgb_to_gray() (when negative + parameters are supplied by the caller), while in the absence of cHRM + sRGB/Rec 709 values are still used. + The bKGD chunk no longer overwrites the background value set by + png_set_background(), allowing the latter to be used before the file + header is read. It never performed any useful function to override + the default anyway. + Added memory overwrite and palette image checks to pngvalid.c + Previously palette image code was poorly checked. Since the transformation + code has a special palette path in most cases this was a severe weakness. + Minor cleanup and some extra checking in pngrutil.c and pngrtran.c. When + expanding an indexed image, always expand to RGBA if transparency is + present. + +Version 1.5.3beta09 [May 17, 2011] + Reversed earlier 1.5.3 change of transformation order; move png_expand_16 + back where it was. The change doesn't work because it requires 16-bit + gamma tables when the code only generates 8-bit ones. This fails + silently; the libpng code just doesn't do any gamma correction. Moving + the tests back leaves the old, inaccurate, 8-bit gamma calculations, but + these are clearly better than none! + +Version 1.5.3beta10 [May 20, 2011] + + png_set_background() and png_expand_16() did not work together correctly. + This problem is present in 1.5.2; if png_set_background is called with + need_expand false and the matching 16 bit color libpng erroneously just + treats it as an 8-bit color because of where png_do_expand_16 is in the + transform list. This simple fix reduces the supplied colour to 8-bits, + so it gets smashed, but this is better than the current behavior. + Added tests for expand16, more fixes for palette image tests to pngvalid. + Corrects the code for palette image tests and disables attempts to + validate palette colors. + +Version 1.5.3rc01 [June 3, 2011] + No changes. + +Version 1.5.3rc02 [June 8, 2011] + Fixed uninitialized memory read in png_format_buffer() (Bug report by + Frank Busse, CVE-2011-2501, related to CVE-2004-0421). + +Version 1.5.3beta11 [June 11, 2011] + Fixed png_handle_sCAL which is broken in 1.5; added sCAL to pngtest.png + Revised documentation about png_set_user_limits() to say that it also affects + png writing. + Revised handling of png_set_user_limits() so that it can increase the + limit beyond the PNG_USER_WIDTH|HEIGHT_MAX; previously it could only + reduce it. + Make the 16-to-8 scaling accurate. Dividing by 256 with no rounding is + wrong (high by one) 25% of the time. Dividing by 257 with rounding is + wrong in 128 out of 65536 cases. Getting the right answer all the time + without division is easy. + Added "_SUPPORTED" to the PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION macro. + Added projects/owatcom, an IDE project for OpenWatcom to replace + scripts/makefile.watcom. This project works with OpenWatcom 1.9. The + IDE autogenerates appropriate makefiles (libpng.mk) for batch processing. + The project is configurable, unlike the Visual Studio project, so long + as the developer has an awk. + Changed png_set_gAMA to limit the gamma value range so that the inverse + of the stored value cannot overflow the fixed point representation, + and changed other things OpenWatcom warns about. + Revised pngvalid.c to test PNG_ALPHA_MODE_SUPPORTED correctly. This allows + pngvalid to build when ALPHA_MODE is not supported, which is required if + it is to build on libpng 1.4. + Removed string/memory macros that are no longer used and are not + necessarily fully supportable, particularly png_strncpy and png_snprintf. + Added log option to pngvalid.c and attempted to improve gamma messages. + +Version 1.5.3 [omitted] + People found the presence of a beta release following an rc release + to be confusing; therefore we bump the version to libpng-1.5.4beta01 + and there will be no libpng-1.5.3 release. + +Version 1.5.4beta01 [June 14, 2011] + Made it possible to undefine PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED + to get the same (inaccurate) output as libpng-1.5.2 and earlier. + Moved definitions of PNG_HAVE_IHDR, PNG_AFTER_IDAT, and PNG_HAVE_PLTE + outside of an unknown-chunk block in png.h because they are also + needed for other uses. + +Version 1.5.4beta02 [June 14, 2011] + Fixed and clarified LEGACY 16-to-8 scaling code. + Added png_set_chop_16() API, to match inaccurate results from previous + libpng versions. + Removed the ACCURATE and LEGACY options (they are no longer useable) + Use the old scaling method for background if png_set_chop_16() was + called. + Made png_set_chop_16() API removeable by disabling PNG_CHOP_16_TO_8_SUPPORTED + +Version 1.5.4beta03 [June 15, 2011] + Fixed a problem in png_do_expand_palette() exposed by optimization in + 1.5.3beta06 + Also removed a spurious and confusing "trans" member ("trans") from png_info. + The palette expand optimization prevented expansion to an intermediate RGBA + form if tRNS was present but alpha was marked to be stripped; this exposed + a check for tRNS in png_do_expand_palette() which is inconsistent with the + code elsewhere in libpng. + Correction to the expand_16 code; removed extra instance of + png_set_scale_16_to_8 from pngpriv.h + +Version 1.5.4beta04 [June 16, 2011] + Added a missing "#ifdef PNG_READ_BACKGROUND_SUPPORTED/#endif" in pngrtran.c + Added PNG_TRANSFORM_CHOP_16 to the high-level read transforms. + Made PNG_READ_16_TO_8_ACCURATE_SCALE configurable again. If this is + not enabled, png_set_strip_16() and png_do_scale_16_to_8() aren't built. + Revised contrib/visupng, gregbook, and pngminim to demonstrate chop_16_to_8 + +Version 1.5.4beta05 [June 16, 2011] + Renamed png_set_strip_16() to png_set_scale_16() and renamed + png_set_chop_16() to png_set_strip(16) in an attempt to minimize the + behavior changes between libpng14 and libpng15. + +Version 1.5.4beta06 [June 18, 2011] + Fixed new bug that was causing both strip_16 and scale_16 to be applied. + +Version 1.5.4beta07 [June 19, 2011] + Fixed pngvalid, simplified macros, added checking for 0 in sCAL. + The ACCURATE scale macro is no longer defined in 1.5 - call the + png_scale_16_to_8 API. Made sure that PNG_READ_16_TO_8 is still defined + if the png_strip_16_to_8 API is present. png_check_fp_number now + maintains some state so that positive, negative and zero values are + identified. sCAL uses these to be strictly spec conformant. + +Version 1.5.4beta08 [June 23, 2011] + Fixed pngvalid if ACCURATE_SCALE is defined. + Updated scripts/pnglibconf.h.prebuilt. + +Version 1.5.4rc01 [June 30, 2011] + Define PNG_ALLOCATED to "restrict" only if MSC_VER >= 1400. + +Version 1.5.4 [July 7, 2011] + Send comments/corrections/commendations to png-mng-implement at lists.sf.net (subscription required; visit https://lists.sourceforge.net/lists/listinfo/png-mng-implement diff --git a/src/3rdparty/libpng/CMakeLists.txt b/src/3rdparty/libpng/CMakeLists.txt index 2ee5bf3..cc15850 100644 --- a/src/3rdparty/libpng/CMakeLists.txt +++ b/src/3rdparty/libpng/CMakeLists.txt @@ -33,7 +33,7 @@ enable_testing() set(PNGLIB_MAJOR 1) set(PNGLIB_MINOR 5) -set(PNGLIB_RELEASE 1) +set(PNGLIB_RELEASE 4) set(PNGLIB_NAME libpng${PNGLIB_MAJOR}${PNGLIB_MINOR}) set(PNGLIB_VERSION ${PNGLIB_MAJOR}.${PNGLIB_MINOR}.${PNGLIB_RELEASE}) @@ -147,10 +147,6 @@ set(pngtest_sources add_definitions(-DPNG_CONFIGURE_LIBPNG) -if(_AIX) - add_definitions(-D_ALL_SOURCE) -endif(_AIX) - if(MSVC) add_definitions(-DPNG_NO_MODULEDEF -D_CRT_SECURE_NO_DEPRECATE) endif(MSVC) @@ -264,7 +260,7 @@ install(CODE ${PNG_CONFIG_INSTALL_CODE}) # SET UP LINKS if(PNG_SHARED) set_target_properties(${PNG_LIB_NAME} PROPERTIES -# VERSION 15.${PNGLIB_RELEASE}.1.5.1 +# VERSION 15.${PNGLIB_RELEASE}.1.5.4 VERSION 15.${PNGLIB_RELEASE}.0 SOVERSION 15 CLEAN_DIRECT_OUTPUT 1) diff --git a/src/3rdparty/libpng/LICENSE b/src/3rdparty/libpng/LICENSE index b28f15c..89f5243 100644 --- a/src/3rdparty/libpng/LICENSE +++ b/src/3rdparty/libpng/LICENSE @@ -10,7 +10,7 @@ this sentence. This code is released under the libpng license. -libpng versions 1.2.6, August 15, 2004, through 1.5.1, February 3, 2011, are +libpng versions 1.2.6, August 15, 2004, through 1.5.4, July 7, 2011, are Copyright (c) 2004, 2006-2011 Glenn Randers-Pehrson, and are distributed according to the same disclaimer and license as libpng-1.2.5 with the following individual added to the list of Contributing Authors @@ -108,4 +108,4 @@ certification mark of the Open Source Initiative. Glenn Randers-Pehrson glennrp at users.sourceforge.net -February 3, 2011 +July 7, 2011 diff --git a/src/3rdparty/libpng/README b/src/3rdparty/libpng/README index 9dd6745..71396a8 100644 --- a/src/3rdparty/libpng/README +++ b/src/3rdparty/libpng/README @@ -1,4 +1,4 @@ -README for libpng version 1.5.1 - February 3, 2011 (shared library 15.0) +README for libpng version 1.5.4 - July 7, 2011 (shared library 15.0) See the note about version numbers near the top of png.h See INSTALL for instructions on how to install libpng. @@ -114,19 +114,16 @@ given in previous versions of this document. He and Andreas will read mail addressed to the png-implement list, however. Please do not send general questions about PNG. Send them to -the (png-list at ccrc.wustl.edu, subscription required, write to -majordomo at ccrc.wustl.edu with "subscribe png-list" in your message). -On the other hand, -please do not send libpng questions to that address, send them to me -or to the png-implement list. I'll -get them in the end anyway. If you have a question about something +png-mng-misc at lists.sf.net (subscription required; visit +https://lists.sourceforge.net/lists/listinfo/png-mng-misc to +subscribe). If you have a question about something in the PNG specification that is related to using libpng, send it to me. Send me any questions that start with "I was using libpng, and ...". If in doubt, send questions to me. I'll bounce them to others, if necessary. Please do not send suggestions on how to change PNG. We have -been discussing PNG for nine years now, and it is official and +been discussing PNG for sixteen years now, and it is official and finished. If you have suggestions for libpng, however, I'll gladly listen. Even if your suggestion is not used immediately, it may be used later. diff --git a/src/3rdparty/libpng/configure.ac b/src/3rdparty/libpng/configure.ac index ff277a4..f2800f6 100644 --- a/src/3rdparty/libpng/configure.ac +++ b/src/3rdparty/libpng/configure.ac @@ -18,15 +18,15 @@ AC_PREREQ(2.59) dnl Version number stuff here: -AC_INIT([libpng], [1.5.1], [png-mng-implement@lists.sourceforge.net]) +AC_INIT([libpng], [1.5.4], [png-mng-implement@lists.sourceforge.net]) AM_INIT_AUTOMAKE dnl stop configure from automagically running automake AM_MAINTAINER_MODE -PNGLIB_VERSION=1.5.1 +PNGLIB_VERSION=1.5.4 PNGLIB_MAJOR=1 PNGLIB_MINOR=5 -PNGLIB_RELEASE=1 +PNGLIB_RELEASE=4 dnl End of version number stuff diff --git a/src/3rdparty/libpng/example.c b/src/3rdparty/libpng/example.c index cd3682f..c0d27f4 100644 --- a/src/3rdparty/libpng/example.c +++ b/src/3rdparty/libpng/example.c @@ -2,7 +2,7 @@ #if 0 /* in case someone actually tries to compile this */ /* example.c - an example of using libpng - * Last changed in libpng 1.5.0 [January 6, 2011] + * Last changed in libpng 1.5.4 [July 7, 2011] * This file has been placed in the public domain by the authors. * Maintained 1998-2011 Glenn Randers-Pehrson * Maintained 1996, 1997 Andreas Dilger) @@ -22,6 +22,10 @@ * see also the programs in the contrib directory. */ +#define _POSIX_SOURCE 1 /* libpng and zlib are POSIX-compliant. You may + * change this if your application uses non-POSIX + * extensions. */ + #include "png.h" /* The png_jmpbuf() macro, used in error handling, became available in @@ -183,8 +187,15 @@ void read_png(FILE *fp, unsigned int sig_read) /* File is already open */ * are mutually exclusive. */ - /* Tell libpng to strip 16 bit/color files down to 8 bits/color */ + /* Tell libpng to strip 16 bit/color files down to 8 bits/color. + * Use accurate scaling if it's available, otherwise just chop off the + * low byte. + */ +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED + png_set_scale_16(png_ptr); +#else png_set_strip_16(png_ptr); +#endif /* Strip alpha bytes from the input data without combining with the * background (not recommended). diff --git a/src/3rdparty/libpng/libpng-manual.txt b/src/3rdparty/libpng/libpng-manual.txt index 77adf7a..c91b99c 100644 --- a/src/3rdparty/libpng/libpng-manual.txt +++ b/src/3rdparty/libpng/libpng-manual.txt @@ -1,6 +1,6 @@ libpng-manual.txt - A description on how to use and modify libpng - libpng version 1.5.1 - February 3, 2011 + libpng version 1.5.4 - July 7, 2011 Updated and distributed by Glenn Randers-Pehrson <glennrp at users.sourceforge.net> Copyright (c) 1998-2011 Glenn Randers-Pehrson @@ -11,7 +11,7 @@ libpng-manual.txt - A description on how to use and modify libpng Based on: - libpng versions 0.97, January 1998, through 1.5.1 - February 3, 2011 + libpng versions 0.97, January 1998, through 1.5.4 - July 7, 2011 Updated and distributed by Glenn Randers-Pehrson Copyright (c) 1998-2011 Glenn Randers-Pehrson @@ -198,9 +198,9 @@ reconfiguration of pnglibconf.h. To reconfigure pnglibconf.h it must either be rebuilt from scripts/pnglibconf.dfa using awk or it must be edited by hand. Hand editing is achieved by copying scripts/pnglibconf.h.prebuilt and changing -the lines defining the supported features, paying very close attention to the -'option' information in scripts/pnglibconf.dfa that describes those features and -their requirements. This is easy to get wrong. +the lines defining the supported features, paying very close attention to +the 'option' information in scripts/pnglibconf.dfa that describes those +features and their requirements. This is easy to get wrong. B. Configuration using DFA_XTRA @@ -348,21 +348,12 @@ create the structure, so your application should check for that. return (ERROR); } - png_infop end_info = png_create_info_struct(png_ptr); - - if (!end_info) - { - png_destroy_read_struct(&png_ptr, &info_ptr, - (png_infopp)NULL); - return (ERROR); - } - If you want to use your own memory allocation routines, use a libpng that was built with PNG_USER_MEM_SUPPORTED defined, and use png_create_read_struct_2() instead of png_create_read_struct(): png_structp png_ptr = png_create_read_struct_2 - (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, user_error_fn, user_warning_fn, (png_voidp) user_mem_ptr, user_malloc_fn, user_free_fn); @@ -374,7 +365,7 @@ handling and memory alloc/free functions. When libpng encounters an error, it expects to longjmp back to your routine. Therefore, you will need to call setjmp and pass your png_jmpbuf(png_ptr). If you read the file from different -routines, you will need to update the jmpbuf field every time you enter +routines, you will need to update the longjmp buffer every time you enter a new routine that will call a png_*() function. See your documentation of setjmp/longjmp for your compiler for more @@ -392,6 +383,9 @@ free any memory. return (ERROR); } +Pass (png_infopp)NULL instead of &end_info if you didn't create +an end_info structure. + If you would rather avoid the complexity of setjmp/longjmp issues, you can compile libpng with PNG_NO_SETJMP, in which case errors will result in a call to PNG_ABORT() which defaults to abort(). @@ -513,6 +507,19 @@ To inform libpng about your function, use png_set_read_status_fn(png_ptr, read_row_callback); +When this function is called the row has already been completely processed and +the 'row' and 'pass' refer to the next row to be handled. For the +non-interlaced case the row that was just handled is simply one less than the +passed in row number, and pass will always be 0. For the interlaced case the +same applies unless the row value is 0, in which case the row just handled was +the last one from one of the preceding passes. Because interlacing may skip a +pass you cannot be sure that the preceding pass is just 'pass-1', if you really +need to know what the last pass is record (row,pass) from the callback and use +the last recorded value each time. + +As with the user transform you can find the output row using the +PNG_ROW_FROM_PASS_ROW macro. + Unknown-chunk handling Now you get to set the way the library processes unknown chunks in the @@ -590,7 +597,7 @@ large as 2^31-1 (0x7fffffff), or about 2.147 billion rows and columns. Since very few applications really need to process such large images, we have imposed an arbitrary 1-million limit on rows and columns. Larger images will be rejected immediately with a png_error() call. If -you wish to override this limit, you can use +you wish to change this limit, you can use png_set_user_limits(png_ptr, width_max, height_max); @@ -600,6 +607,10 @@ anyway because of potential buffer overflow conditions). You should put this statement after you create the PNG structure and before calling png_read_info(), png_read_png(), or png_process_data(). + +When writing a PNG datastream, put this statement before calling +png_write_info() or png_write_png(). + If you need to retrieve the limits that are being applied, use width_max = png_get_user_width_max(png_ptr); @@ -630,6 +641,234 @@ and you can retrieve the limit with Any chunks that would cause either of these limits to be exceeded will be ignored. +Information about your system + +If you intend to display the PNG or to incorporate it in other image data you +need to tell libpng information about your display or drawing surface so that +libpng can convert the values in the image to match the display. + +From libpng-1.5.4 this information can be set before reading the PNG file +header. In earlier versions png_set_gamma() existed but behaved incorrectly if +called before the PNG file header had been read and png_set_alpha_mode() did not +exist. + +If you need to support versions prior to libpng-1.5.4 test the version number +and follow the procedures described in the appropriate manual page. + +You give libpng the encoding expected by your system expressed as a 'gamma' +value. You can also specify a default encoding for the PNG file in +case the required information is missing from the file. By default libpng +assumes that the PNG data matches your system, to keep this default call: + + png_set_gamma(png_ptr, screen_gamma, 1/screen_gamma/*file gamma*/); + +or you can use the fixed point equivalent: + + png_set_gamma_fixed(png_ptr, PNG_FP_1*screen_gamma, PNG_FP_1/screen_gamma); + +If you don't know the gamma for you system it is probably 2.2 - a good +approximation to the IEC standard for display systems (sRGB). If images are +too contrasty or washed out you got the value wrong - check your system +documentation! + +Many systems permit the system gamma to be changed via a lookup table in the +display driver, a few systems, including older Macs, change the response by +default. As of 1.5.4 three special values are available to handle common +situations: + + PNG_DEFAULT_sRGB: Indicates that the system conforms to the IEC 61966-2-1 + standard. This matches almost all systems. + PNG_GAMMA_MAC_18: Indicates that the system is an older (pre Mac OS 10.6) + Apple Macintosh system with the default settings. + PNG_GAMMA_LINEAR: Just the fixed point value for 1.0 - indicates that the + system expects data with no gamma encoding. + +You would use the linear (unencoded) value if you need to process the pixel +values further because this avoids the need to decode and reencode each +component value whenever arithmetic is performed. A lot of graphics software +uses linear values for this reason, often with higher precision component values +to preserve overall accuracy. + +The second thing you may need to tell libpng about is how your system handles +alpha channel information. Some, but not all, PNG files contain an alpha +channel. To display these files correctly you need to compose the data onto a +suitable background, as described in the PNG specification. + +Libpng only supports composing onto a single color (using png_set_background; +see below.) Otherwise you must do the composition yourself and, in this case, +you may need to call png_set_alpha_mode: + + png_set_alpha_mode(png_ptr, mode, screen_gamma); + +The screen_gamma value is the same as the argument to png_set_gamma, however how +it affects the output depends on the mode. png_set_alpha_mode() sets the file +gamma default to 1/screen_gamma, so normally you don't need to call +png_set_gamma. If you need different defaults call png_set_gamma() before +png_set_alpha_mode() - if you call it after it will override the settings made +by png_set_alpha_mode(). + +The mode is as follows: + + PNG_ALPHA_PNG: The data is encoded according to the PNG specification. Red, +green and blue, or gray, components are gamma encoded color +values and are not premultiplied by the alpha value. The +alpha value is a linear measure of the contribution of the +pixel to the corresponding final output pixel. + +You should normally use this format if you intend to perform +color correction on the color values; most, maybe all, color +correction software has no handling for the alpha channel and, +anyway, the math to handle pre-multiplied component values is +unnecessarily complex. + +Before you do any arithmetic on the component values you need +to remove the gamma encoding and multiply out the alpha +channel. See the PNG specification for more detail. It is +important to note that when an image with an alpha channel is +scaled, linear encoded, pre-multiplied component values must +be used! + +The remaining modes assume you don't need to do any further color correction or +that if you do your color correction software knows all about alpha (it +probably doesn't!) + + PNG_ALPHA_STANDARD: The data libpng produces is encoded in the standard way +assumed by most correctly written graphics software. +The gamma encoding will be removed by libpng and the +linear component values will be pre-multiplied by the +alpha channel. + +With this format the final image must be re-encoded to +match the display gamma before the image is displayed. +If your system doesn't do that, yet still seems to +perform arithmetic on the pixels without decoding them, +it is broken - check out the modes below. + +With PNG_ALPHA_STANDARD libpng always produces linear +component values, whatever screen_gamma you supply. The +screen_gamma value is, however, used as a default for +the file gamma if the PNG file has no gamma information. + +If you call png_set_gamma() after png_set_alpha_mode() you +will override the linear encoding. Instead the +pre-multiplied pixel values will be gamma encoded but +the alpha channel will still be linear. This may +actually match the requirements of some broken software, +but it is unlikely. + +While linear 8-bit data is often used it has +insufficient precision for any image with a reasonable +dynamic range. To avoid problems, and if your software +supports it, use png_set_expand_16() to force all +components to 16 bits. + + PNG_ALPHA_OPTIMIZED: This mode is the same as PNG_ALPHA_STANDARD except that +completely opaque pixels are gamma encoded according to +the screen_gamma value. Pixels with alpha less than 1.0 +will still have linear components. + +Use this format if you have control over your +compositing software and do don't do other arithmetic +(such as scaling) on the data you get from libpng. Your +compositing software can simply copy opaque pixels to +the output but still has linear values for the +non-opaque pixels. + +In normal compositing, where the alpha channel encodes +partial pixel coverage (as opposed to broad area +translucency), the inaccuracies of the 8-bit +representation of non-opaque pixels are irrelevant. + +You can also try this format if your software is broken; +it might look better. + + PNG_ALPHA_BROKEN: This is PNG_ALPHA_STANDARD however all component values, +including the alpha channel are gamma encoded. This is +an appropriate format to try if your software, or more +likely hardware, is totally broken: if it performs +linear arithmetic directly on gamma encoded values. + +In most cases of broken software or hardware the bug in the final display +manifests as a subtle halo around composited parts of the image. You may not +even perceive this as a halo; the composited part of the image may simply appear +separate from the background, as though it had been cut out of paper and pasted +on afterward. + +If you don't have to deal with bugs in software or hardware, or if you can fix +them, there are three recommended ways of using png_set_alpha_mode(): + + png_set_alpha_mode(png_ptr, PNG_ALPHA_PNG, + screen_gamma); + +You can do color correction on the result (libpng does not currently +support color correction internally.) When you handle the alpha channel +you need to undo the gamma encoding and multiply out the alpha. + + png_set_alpha_mode(png_ptr, PNG_ALPHA_STANDARD, + screen_gamma); + png_set_expand_16(png_ptr); + +If you are using the high level interface don't call png_set_expand_16(); +instead pass PNG_TRANSFORM_EXPAND_16 to the interface. + +With this mode you can't do color correction, but you can do arithmetic, +including composition and scaling, on the data without further processing. + + png_set_alpha_mode(png_ptr, PNG_ALPHA_OPTIMIZED, + screen_gamma); + +You can avoid the expansion to 16-bit components with this mode, but you +lose the ability to scale the image or perform other linear arithmetic. +All you can do is compose the result onto a matching output. Since this +mode is libpng specific you also need to write your own composition +software. + +If you don't need, or can't handle, the alpha channel you can call +png_set_background() to remove it by compositing against a fixed color. Don't +call png_set_strip_alpha() to do this - it will leave spurious pixel values in +transparent parts of this image. + + png_set_background(png_ptr, &background_color, + PNG_BACKGROUND_GAMMA_SCREEN, 0, 1); + +The background_color is an RGB or grayscale value according to the data format +libpng will produce for you. Because you don't yet know the format of the PNG +file if you call png_set_background at this point you must arrange for the +format produced by libpng to always have 8-bit or 16-bit components and then +store the color as an 8-bit or 16-bit color as appropriate. The color contains +separate gray and RGB component values, so you can let libpng produce gray or +RGB output according to the input format, but low bit depth grayscale images +must always be converted to at least 8-bit format. (Even low low bit depth +grayscale images can't have an alpha channel they can have a transparent +color!) + +You set the transforms you need later, either as flags to the high level +interface or libpng API calls for the low level interface. For reference the +settings and API calls required are: + +8-bit values: + PNG_TRANSFORM_SCALE_16 | PNG_EXPAND + png_set_expand(png_ptr); png_set_scale_16(png_ptr); + + If you must get exactly the same inaccurate results + produced by default in versions prior to libpng-1.5.4, + use PNG_TRANSFORM_STRIP_16 and png_set_strip_16(png_ptr) + instead. + +16-bit values: + PNG_TRANSFORM_EXPAND_16 + png_set_expand_16(png_ptr); + +In either case palette image data will be expanded to RGB. If you just want +color data you can add PNG_TRANSFORM_GRAY_TO_RGB or png_set_gray_to_rgb(png_ptr) +to the list. + +Calling png_set_background before the PNG file header is read will not work +prior to libpng-1.5.4. Because the failure may result in unexpected warnings or +errors it is therefore much safer to call png_set_background after the head has +been read. Unfortunately this means that prior to libpng-1.5.4 it cannot be +used with the high level interface. + The high-level read interface At this point there are two ways to proceed; through the high-level @@ -639,8 +878,10 @@ the entire image into memory, and (b) the input transformations you want to do are limited to the following set: PNG_TRANSFORM_IDENTITY No transformation - PNG_TRANSFORM_STRIP_16 Strip 16-bit samples to - 8 bits + PNG_TRANSFORM_SCALE_16 Strip 16-bit samples to + 8-bit accurately + PNG_TRANSFORM_STRIP_16 Chop 16-bit samples to + 8-bit less accurately PNG_TRANSFORM_STRIP_ALPHA Discard the alpha channel PNG_TRANSFORM_PACKING Expand 1, 2 and 4-bit samples to bytes @@ -659,6 +900,7 @@ you want to do are limited to the following set: PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples PNG_TRANSFORM_GRAY_TO_RGB Expand grayscale samples to RGB (or GA to RGBA) + PNG_TRANSFORM_EXPAND_16 Expand samples to 16 bits (This excludes setting a background color, doing gamma transformation, quantizing, and setting filler.) If this is the case, simply do this: @@ -727,6 +969,22 @@ call to png_read_info(). This will process all chunks up to but not including the image data. +This also copies some of the data from the PNG file into the decode structure +for use in later transformations. Important information copied in is: + +1) The PNG file gamma from the gAMA chunk. This overwrites the default value +provided by an earlier call to png_set_gamma or png_set_alpha_mode. + +2) Prior to libpng-1.5.4 the background color from a bKGd chunk. This +damages the information provided by an earlier call to png_set_background +resulting in expected behavior. Libpng-1.5.4 no longer does this. + +3) The number of significant bits in each component value. Libpng uses this to +optimize gamma handling by reducing the internal lookup table sizes. + +4) The transparent color information from a tRNS chunk. This can be modified by +a later call to png_set_tRNS. + Querying the info structure Functions are used to get the information from the info_ptr once it @@ -1069,7 +1327,7 @@ forms: 72 dpi is stored as 0.28346 pixels/meter, and when this is retrieved it is 71.9988 dpi, so be sure to round the returned value appropriately - if you want to display a reasonable-looking result. + if you want to display a reasonable-looking result. The data from the oFFs chunk can be retrieved in several convenient forms: @@ -1090,7 +1348,7 @@ forms: converted to microns and back without some loss of precision. -For more information, see the png_info definition in png.h and the +For more information, see the PNG specification for chunk contents. Be careful with trusting rowbytes, as some of the transformations could increase the space needed to hold a row (expand, filler, gray_to_rgb, etc.). @@ -1125,17 +1383,20 @@ to handle any special transformations of the image data. The various ways to transform the data will be described in the order that they should occur. This is important, as some of these change the color type and/or bit depth of the data, and some others only work on -certain color types and bit depths. Even though each transformation -checks to see if it has data that it can do something with, you should -make sure to only enable a transformation if it will be valid for the -data. For example, don't swap red and blue on grayscale data. +certain color types and bit depths. + +Transformations you request are ignored if they don't have any meaning for a +particular input data format. However some transformations can have an effect +as a result of a previous transformation. If you specify a contradictory set of +transformations, for example both adding and removing the alpha channel, you +cannot predict the final result. -The colors used for the background and transparency values should be -supplied in the same format/depth as the current image data. They -are stored in the same format/depth as the image data in a bKGD or tRNS -chunk, so this is what libpng expects for this data. The colors are -transformed to keep in sync with the image data when an application -calls the png_read_update_info() routine (see below). +The color used for the transparency values should be supplied in the same +format/depth as the current image data. It is stored in the same format/depth +as the image data in a tRNS chunk, so this is what libpng expects for this data. + +The color used for the background value depends on the need_expand argument as +described below. Data will be decoded into the supplied row buffers packed into bytes unless the library has been told to transform it into another format. @@ -1145,12 +1406,12 @@ byte, unless png_set_packing() is called. 8-bit RGB data will be stored in RGB RGB RGB format unless png_set_filler() or png_set_add_alpha() is called to insert filler bytes, either before or after each RGB triplet. 16-bit RGB data will be returned RRGGBB RRGGBB, with the most significant -byte of the color value first, unless png_set_strip_16() is called to +byte of the color value first, unless png_set_scale_16() is called to transform it to regular RGB RGB triplets, or png_set_filler() or png_set_add alpha() is called to insert filler bytes, either before or after each RRGGBB triplet. Similarly, 8-bit or 16-bit grayscale data can -be modified with -png_set_filler(), png_set_add_alpha(), or png_set_strip_16(). +be modified with png_set_filler(), png_set_add_alpha(), png_set_strip_16(), +or png_set_scale_16(). The following code transforms grayscale images of less than 8 to 8 bits, changes paletted images to RGB, and adds a full alpha channel if there is @@ -1161,13 +1422,13 @@ viewing application that wishes to treat all images in the same way. if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); - if (color_type == PNG_COLOR_TYPE_GRAY && - bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); -These three functions are actually aliases for png_set_expand(), added + if (color_type == PNG_COLOR_TYPE_GRAY && + bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); + +The first two functions are actually aliases for png_set_expand(), added in libpng version 1.0.4, with the function names expanded to improve code readability. In some future version they may actually do different things. @@ -1175,56 +1436,84 @@ things. As of libpng version 1.2.9, png_set_expand_gray_1_2_4_to_8() was added. It expands the sample depth without changing tRNS to alpha. -As of libpng version 1.5.1, not all possible expansions are supported. +As of libpng version 1.5.2, png_set_expand_16() was added. It behaves as +png_set_expand(), however, the resultant channels have 16 bits rather than 8. +Use this when the output color or gray channels are made linear to avoid fairly +severe accuracy loss. + + if (bit_depth < 16) + png_set_expand_16(png_ptr); + +PNG can have files with 16 bits per channel. If you only can handle +8 bits per channel, this will strip the pixels down to 8-bit. + + if (bit_depth == 16) + png_set_scale_16(png_ptr); + +If you need to process the alpha channel on the image separately from the image +data (for example if you convert it to a bitmap mask) it is possible to have +libpng strip the channel leaving just RGB or gray data: + + if (color_type & PNG_COLOR_MASK_ALPHA) + png_set_strip_alpha(png_ptr); + +If you strip the alpha channel you need to find some other way of dealing with +the information. If, instead, you want to convert the image to an opaque +version with no alpha channel use png_set_background; see below. + +As of libpng version 1.5.2, almost all useful expansions are supported, the +major ommissions are conversion of grayscale to indexed images (which can be +done trivially in the application) and conversion of indexed to grayscale (which +can be done by a trivial manipulation of the palette.) In the following table, the 01 means grayscale with depth<8, 31 means indexed with depth<8, other numerals represent the color type, "T" means the tRNS chunk is present, A means an alpha channel is present, and O means tRNS or alpha is present but all pixels in the image are opaque. - FROM 01 31 0 0T 0O 2 2T 2O 3 3T 3O 4A 4O 6A 6O + FROM 01 31 0 0T 0O 2 2T 2O 3 3T 3O 4A 4O 6A 6O TO - 01 - - 31 - - 0 1 - - 0T - - 0O - - 2 GX - - 2T - - 2O - - 3 1 - - 3T - - 3O - - 4A T - - 4O - - 6A GX TX TX - - 6O GX TX - + 01 - [G] - - - - - - - - - - - - - + 31 [Q] Q [Q] [Q] [Q] Q Q Q Q Q Q [Q] [Q] Q Q + 0 1 G + . . G G G G G G B B GB GB + 0T lt Gt t + . Gt G G Gt G G Bt Bt GBt GBt + 0O lt Gt t . + Gt Gt G Gt Gt G Bt Bt GBt GBt + 2 C P C C C + . . C - - CB CB B B + 2T Ct - Ct C C t + t - - - CBt CBt Bt Bt + 2O Ct - Ct C C t t + - - - CBt CBt Bt Bt + 3 [Q] p [Q] [Q] [Q] Q Q Q + . . [Q] [Q] Q Q + 3T [Qt] p [Qt][Q] [Q] Qt Qt Qt t + t [Qt][Qt] Qt Qt + 3O [Qt] p [Qt][Q] [Q] Qt Qt Qt t t + [Qt][Qt] Qt Qt + 4A lA G A T T GA GT GT GA GT GT + BA G GBA + 4O lA GBA A T T GA GT GT GA GT GT BA + GBA G + 6A CA PA CA C C A T tT PA P P C CBA + BA + 6O CA PBA CA C C A tT T PA P P CBA C BA + Within the matrix, + "+" identifies entries where 'from' and 'to' are the same. "-" means the transformation is not supported. + "." means nothing is necessary (a tRNS chunk can just be ignored). + "t" means the transformation is obtained by png_set_tRNS. + "A" means the transformation is obtained by png_set_add_alpha(). "X" means the transformation is obtained by png_set_expand(). "1" means the transformation is obtained by - png_set_expand_gray_1_2_4_to_8 - "G" means the transformation is obtained by - png_set_gray_to_rgb(). + png_set_expand_gray_1_2_4_to_8() (and by png_set_expand() if there + is no transparency in the original or the final format). + "C" means the transformation is obtained by png_set_gray_to_rgb(). + "G" means the transformation is obtained by png_set_rgb_to_gray(). "P" means the transformation is obtained by png_set_expand_palette_to_rgb(). - "T" means the transformation is obtained by - png_set_tRNS_to_alpha(). - -PNG can have files with 16 bits per channel. If you only can handle -8 bits per channel, this will strip the pixels down to 8 bit. - - if (bit_depth == 16) - png_set_strip_16(png_ptr); - -If, for some reason, you don't need the alpha channel on an image, -and you want to remove it rather than combining it with the background -(but the image author certainly had in mind that you *would* combine -it with the background, so that's what you should probably do): - - if (color_type & PNG_COLOR_MASK_ALPHA) - png_set_strip_alpha(png_ptr); + "p" means the transformation is obtained by png_set_packing(). + "Q" means the transformation is obtained by png_set_quantize(). + "T" means the transformation is obtained by png_set_tRNS_to_alpha(). + "B" means the transformation is obtained by png_set_background(), or + png_strip_alpha(). + +When an entry has multiple transforms listed all are required to cause the +right overall transformation. When two transforms are separated by a comma +either will do the job. When transforms are enclosed in [] the transform should +do the job but this is currently unimplemented - a different format will result +if the suggested transformations are used. In PNG files, the alpha channel in an image is the level of opacity. If you need the alpha channel in an image to @@ -1303,8 +1592,8 @@ with alpha. if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA) - png_set_rgb_to_gray_fixed(png_ptr, error_action, - int red_weight, int green_weight); + png_set_rgb_to_gray(png_ptr, error_action, double red_weight, + double green_weight); error_action = 1: silently do the conversion @@ -1317,122 +1606,89 @@ with alpha. image has any pixel where red != green or red != blue - red_weight: weight of red component times 100000 + red_weight: weight of red component - green_weight: weight of green component times 100000 + green_weight: weight of green component If either weight is negative, default - weights (21268, 71514) are used. + weights are used. + +In the corresponding fixed point API the red_weight and green_weight values are +simply scaled by 100,000: + + png_set_rgb_to_gray(png_ptr, error_action, png_fixed_point red_weight, + png_fixed_point green_weight); If you have set error_action = 1 or 2, you can later check whether the image really was gray, after processing the image rows, with the png_get_rgb_to_gray_status(png_ptr) function. It will return a png_byte that is zero if the image was gray or -1 if there were any non-gray pixels. bKGD and sBIT data +1 if there were any non-gray pixels. Background and sBIT data will be silently converted to grayscale, using the green channel -data, regardless of the error_action setting. - -With red_weight+green_weight<=100000, -the normalized graylevel is computed: +data for sBIT, regardless of the error_action setting. - int rw = red_weight * 65536; - int gw = green_weight * 65536; - int bw = 65536 - (rw + gw); - gray = (rw*red + gw*green + bw*blue)/65536; +The default values come from the PNG file cHRM chunk if present, otherwise the +defaults correspond to the ITU-R recommendation 709, and also the sRGB color +space, as recommended in the Charles Poynton's Colour FAQ, +<http://www.poynton.com/>, in section 9: -The default values approximate those recommended in the Charles -Poynton's Color FAQ, <http://www.inforamp.net/~poynton/> -Copyright (c) 1998-01-04 Charles Poynton <poynton at inforamp.net> + <http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC9> Y = 0.212671 * R + 0.715160 * G + 0.072169 * B -Libpng approximates this with integers scaled by 32768: - - Y = (6968 * R + 23434 * G + 2366 * B)/32768 - The calculation is done in a linear colorspace, if the image gamma can be determined. -If you have a grayscale and you are using png_set_expand_depth(), -png_set_expand(), or png_set_gray_to_rgb to change to truecolor or to -a higher bit-depth, you must either supply the background color as a gray -value at the original file bit-depth (need_expand = 1) or else supply the -background color as an RGB triplet at the final, expanded bit depth -(need_expand = 0). Similarly, if you are reading a paletted image, you -must either supply the background color as a palette index (need_expand = 1) -or as an RGB triplet that may or may not be in the palette (need_expand = 0). +The png_set_background() function has been described already, it tells libpng to +composite images with alpha or simple transparency against the supplied +background color. For compatibility with versions of libpng earlier than +libpng-1.5.4 it is recommended that you call the function after reading the file +header, even if you don't want to use the color in a bKGD chunk, if one exists. + +If the PNG file contains a bKGD chunk (PNG_INFO_bKGD valid), +you may use this color, or supply another color more suitable for +the current display (e.g., the background color from a web page). You +need to tell libpng how the color is represented, both the format of the +component values in the color (the number of bits) and the gamme encoding of the +color. The function takes two arguments, background_gamma_mode and need_expand +to convey this information, however only two combinations are like to be useful: png_color_16 my_background; png_color_16p image_background; if (png_get_bKGD(png_ptr, info_ptr, &image_background)) png_set_background(png_ptr, image_background, - PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); + PNG_BACKGROUND_GAMMA_FILE, 1/*needs to be expanded*/, 1); else png_set_background(png_ptr, &my_background, - PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); + PNG_BACKGROUND_GAMMA_SCREEN, 0/*do not expand*/, 1); -The png_set_background() function tells libpng to composite images -with alpha or simple transparency against the supplied background -color. If the PNG file contains a bKGD chunk (PNG_INFO_bKGD valid), -you may use this color, or supply another color more suitable for -the current display (e.g., the background color from a web page). You -need to tell libpng whether the color is in the gamma space of the -display (PNG_BACKGROUND_GAMMA_SCREEN for colors you supply), the file -(PNG_BACKGROUND_GAMMA_FILE for colors from the bKGD chunk), or one -that is neither of these gammas (PNG_BACKGROUND_GAMMA_UNIQUE - I don't -know why anyone would use this, but it's here). - -To properly display PNG images on any kind of system, the application needs -to know what the display gamma is. Ideally, the user will know this, and -the application will allow them to set it. One method of allowing the user -to set the display gamma separately for each system is to check for a -SCREEN_GAMMA or DISPLAY_GAMMA environment variable, which will hopefully be -correctly set. - -Note that display_gamma is the overall gamma correction required to produce -pleasing results, which depends on the lighting conditions in the surrounding -environment. In a dim or brightly lit room, no compensation other than -the physical gamma exponent of the monitor is needed, while in a dark room -a slightly smaller exponent is better. - - double gamma, screen_gamma; - - if (/* We have a user-defined screen - gamma value */) - { - screen_gamma = user_defined_screen_gamma; - } - /* One way that applications can share the same - screen gamma value */ - else if ((gamma_str = getenv("SCREEN_GAMMA")) - != NULL) - { - screen_gamma = (double)atof(gamma_str); - } +The second call was described above - my_background is in the format of the +final, display, output produced by libpng. Because you now know the format of +the PNG it is possible to avoid the need to choose either 8-bit or 16-bit +output and to retain palette images (the palette colors will be modified +appropriately and the tRNS chunk removed.) However, if you are doing this, +take great care not to ask for transformations without checking first that +they apply! - /* If we don't have another value */ - else - { - screen_gamma = 2.2; /* A good guess for a - PC monitor in a bright office or a dim room */ +In the first call the background color has the original bit depth and color type +of the PNG file. So, for palette images the color is supplied as a palette +index and for low bit greyscale images the color is a reduced bit value in +image_background->gray. - screen_gamma = 2.0; /* A good guess for a - PC monitor in a dark room */ +If you didn't call png_set_gamma() before reading the file header, for example +if you need your code to remain compatible with older versions of libpng prior +to libpng-1.5.4, this is the place to call it. - screen_gamma = 1.7 or 1.0; /* A good - guess for Mac systems */ - } +Do not call it if you called png_set_alpha_mode(); doing so will damage the +settings put in place by png_set_alpha_mode(). (If png_set_alpha_mode() is +supported then you can certainly do png_set_gamma() before reading the PNG +header.) -The functions png_set_gamma() and its fixed point equivalent -png_set_gamma_fixed() handle gamma transformations of the data. -Pass both the file gamma and the current screen_gamma. If the file does -not have a gamma value, you can pass one anyway if you have an idea what -it is (usually 0.45455 is a good guess for GIF images on PCs). Note -that file gammas are inverted from screen gammas. See the discussions -on gamma in the PNG specification for an excellent description of what -gamma is, and why all applications should support it. It is strongly -recommended that PNG viewers support gamma correction. +This API unconditionally sets the screen and file gamma values, so it will +override the value in the PNG file unless it is called before the PNG file +reading starts. For this reason you must always call it with the PNG file +value when you call it in this position: if (png_get_gAMA(png_ptr, info_ptr, &file_gamma)) png_set_gamma(png_ptr, screen_gamma, file_gamma); @@ -1488,7 +1744,7 @@ This function can also be used to invert grayscale and gray-alpha images: color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_invert_mono(png_ptr); -PNG files store 16 bit pixels in network byte order (big-endian, +PNG files store 16-bit pixels in network byte order (big-endian, ie. most significant bits first). This code changes the storage to the other way (little-endian, i.e. least significant bits first, the way PCs store them): @@ -1511,7 +1767,7 @@ with You must supply the function - void read_transform_fn(png_structp png_ptr, row_info_ptr + void read_transform_fn(png_structp png_ptr, png_row_infop row_info, png_bytep data) See pngtest.c for a working example. Your function will be called @@ -1530,6 +1786,14 @@ supported if user transforms are supported, secondly they may well return unexpected results unless the row is actually being processed at the moment they are called. +With interlaced +images the value returned is the row in the input sub-image image. Use +PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to +find the output pixel (x,y) given an interlaced sub-image pixel (row,col,pass). + +The discussion of interlace handling above contains more information on how to +use these values. + You can also set up a pointer to a user structure for use by your callback function, and you can inform libpng that your transform function will change the number of channels or bit depth with the @@ -1772,15 +2036,39 @@ low-level interface, you can finish reading the file. If you are interested in comments or time, which may be stored either before or after the image data, you should pass the separate png_info struct if you want to keep the comments from before and after the image -separate. If you are not interested, you can pass NULL. +separate. + + png_infop end_info = png_create_info_struct(png_ptr); + + if (!end_info) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + return (ERROR); + } png_read_end(png_ptr, end_info); +If you are not interested, you should still call png_read_end() +but you can pass NULL, avoiding the need to create an end_info structure. + + png_read_end(png_ptr, (png_infop)NULL); + +If you don't call png_read_end(), then your file pointer will be +left pointing to the first chunk after the last IDAT, which is probably +not what you want if you expect to read something beyond the end of +the PNG datastream. + When you are done, you can free all memory allocated by libpng like this: png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); +or, if you didn't create an end_info structure, + + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + It is also possible to individually free the info_ptr members that point to libpng-allocated storage with the following function: @@ -2183,6 +2471,20 @@ To inform libpng about your function, use png_set_write_status_fn(png_ptr, write_row_callback); +When this function is called the row has already been completely processed and +it has also been written out. The 'row' and 'pass' refer to the next row to be +handled. For the +non-interlaced case the row that was just handled is simply one less than the +passed in row number, and pass will always be 0. For the interlaced case the +same applies unless the row value is 0, in which case the row just handled was +the last one from one of the preceding passes. Because interlacing may skip a +pass you cannot be sure that the preceding pass is just 'pass-1', if you really +need to know what the last pass is record (row,pass) from the callback and use +the last recorded value each time. + +As with the user transform you can find the output row using the +PNG_ROW_FROM_PASS_ROW macro. + You now have the option of modifying how the compression library will run. The following functions are mainly for testing, but may be useful in some cases, like if you need to write PNG files extremely fast and @@ -2227,11 +2529,13 @@ which changes how much time zlib spends on trying to compress the image data. See the Compression Library (zlib.h and algorithm.txt, distributed with zlib) for details on the compression levels. - /* set the zlib compression level */ + #include zlib.h + + /* Set the zlib compression level */ png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); - /* set other zlib parameters */ + /* Set other zlib parameters for compressing IDAT */ png_set_compression_mem_level(png_ptr, 8); png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY); @@ -2239,7 +2543,15 @@ with zlib) for details on the compression levels. png_set_compression_method(png_ptr, 8); png_set_compression_buffer_size(png_ptr, 8192) -extern PNG_EXPORT(void,png_set_zbuf_size) + /* Set zlib parameters for text compression + * If you don't call these, the parameters + * fall back on those defined for IDAT chunks + */ + png_set_text_compression_mem_level(png_ptr, 8); + png_set_text_compression_strategy(png_ptr, + Z_DEFAULT_STRATEGY); + png_set_text_compression_window_bits(png_ptr, 15); + png_set_text_compression_method(png_ptr, 8); Setting the contents of info for output @@ -2745,7 +3057,7 @@ is required by PNG. png_set_shift(png_ptr, &sig_bit); -PNG files store 16 bit pixels in network byte order (big-endian, +PNG files store 16-bit pixels in network byte order (big-endian, ie. most significant bits first). This code would be used if they are supplied the other way (little-endian, i.e. least significant bits first, the way PCs store them): @@ -2779,8 +3091,8 @@ with You must supply the function - void write_transform_fn(png_structp png_ptr ptr, - row_info_ptr row_info, png_bytep data) + void write_transform_fn(png_structp png_ptr, png_row_infop + row_info, png_bytep data) See pngtest.c for a working example. Your function will be called before any of the other transformations are processed. If supported @@ -2788,9 +3100,15 @@ libpng also supplies an information routine that may be called from your callback: png_get_current_row_number(png_ptr); + png_get_current_pass_number(png_ptr); -This returns the current row passed to the transform. Even with interlaced -images the value returned is the row in the final output image. +This returns the current row passed to the transform. With interlaced +images the value returned is the row in the input sub-image image. Use +PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to +find the output pixel (x,y) given an interlaced sub-image pixel (row,col,pass). + +The discussion of interlace handling above contains more information on how to +use these values. You can also set up a pointer to a user structure for use by your callback function. @@ -3155,7 +3473,7 @@ the simpler ones to get an idea of how they work. Try to find a similar transformation to the one you want to add and copy off of it. More details can be found in the comments inside the code itself. -Configuring for 16 bit platforms +Configuring for 16-bit platforms You will want to look into zconf.h to tell zlib (and thus libpng) that it cannot allocate more then 64K at a time. Even if you can, the memory @@ -3210,6 +3528,7 @@ specify no compression (Z_NO_COMPRESSION = 0), but this would create files larger than just storing the raw bitmap. You can specify the compression level by calling: + #include zlib.h png_set_compression_level(png_ptr, level); Another useful one is to reduce the memory level used by the library. @@ -3220,12 +3539,14 @@ other things, lower levels will result in sections of incompressible data being emitted in smaller stored blocks, with a correspondingly larger relative overhead of up to 15% in the worst case. + #include zlib.h png_set_compression_mem_level(png_ptr, level); The other functions are for configuring zlib. They are not recommended for normal use and may result in writing an invalid PNG file. See zlib.h for more information on what these mean. + #include zlib.h png_set_compression_strategy(png_ptr, strategy); @@ -3623,12 +3944,12 @@ and memset(), respectively. The function png_set_gray_1_2_4_to_8() was removed. It has been deprecated since libpng-1.0.18 and 1.2.9, when it was replaced with png_set_expand_gray_1_2_4_to_8() because the former function also -expanded palette images. +expanded any tRNS chunk to an alpha channel. Macros for png_get_uint_16, png_get_uint_32, and png_get_int_32 were added and are used by default instead of the corresponding functions. Unfortunately, -from libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the +from libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the function) incorrectly returned a value of type png_uint_32. We changed the prototype for png_malloc() from @@ -3658,7 +3979,8 @@ The png_zalloc() function no longer zeroes out the memory that it allocates. Support for dithering was disabled by default in libpng-1.4.0, because -been well tested and doesn't actually "dither". The code was not +it has not been well tested and doesn't actually "dither". +The code was not removed, however, and could be enabled by building libpng with PNG_READ_DITHER_SUPPORTED defined. In libpng-1.4.2, this support was reenabled, but the function was renamed png_set_quantize() to @@ -3671,7 +3993,7 @@ We removed the trailing '.' from the warning and error messages. X. Changes to Libpng from version 1.4.x to 1.5.x -From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the +From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the function) incorrectly returned a value of type png_uint_32. A. Changes that affect users of libpng @@ -3708,7 +4030,8 @@ application code. (It is extremely rare for an application to do this.) Any program that compiled against libpng 1.4 and did not use deprecated features or access internal library structures should compile and work -against libpng 1.5. +against libpng 1.5, except for the change in the prototype for +png_get_iCCP() and png_set_iCCP() API functions mentioned above. libpng 1.5.0 adds PNG_ PASS macros to help in the reading and writing of interlaced images. The macros return the number of rows and columns in @@ -3716,10 +4039,11 @@ each pass and information that can be used to de-interlace and (if absolutely necessary) interlace an image. libpng 1.5.0 adds an API png_longjmp(png_ptr, value). This API calls -the application provided png_longjmp_ptr on the internal, but application +the application-provided png_longjmp_ptr on the internal, but application initialized, jmpbuf. It is provided as a convenience to avoid the need -to use the png_jmpbuf macro, which had the unnecessary side effect of -resetting the internal png_longjmp_ptr value. +initialized, longjmp buffer. It is provided as a convenience to avoid +the need to use the png_jmpbuf macro, which had the unnecessary side +effect of resetting the internal png_longjmp_ptr value. libpng 1.5.0 includes a complete fixed point API. By default this is present along with the corresponding floating point API. In general the @@ -3762,7 +4086,7 @@ reset by pngusr.h or by explicit settings on the compiler command line. These settings may produce compiler warnings or errors in 1.5.0 because of macro redefinition. -From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the +From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the function) incorrectly returned a value of type png_uint_32. libpng 1.5.0 is consistent with the implementation in 1.4.5 and 1.2.x (where the macro did not exist.) @@ -3773,6 +4097,25 @@ PNG_NO_USE_READ_MACROS before including png.h. Notice that this is only supported from 1.5.0 -defining PNG_NO_USE_READ_MACROS prior to 1.5.0 will lead to a link failure. +Prior to libpng-1.5.4, the zlib compressor used the same set of parameters +when compressing the IDAT data and textual data such as zTXt and iCCP. +In libpng-1.5.4 we reinitialized the zlib stream for each type of data. +We added five png_set_text_*() functions for setting the parameters to +use with textual data. + +Prior to libpng-1.5.4, the PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED +option was off by default, and slightly inaccurate scaling occurred. +This option can no longer be turned off, and the choice of accurate +or inaccurate 16-to-8 scaling is by using the new png_set_scale_16_to_8() +API for accurate scaling or the old png_set_strip_16_to_8() API for simple +chopping. + +Prior to libpng-1.5.4, the png_set_user_limits() function could only be +used to reduce the width and height limits from the value of +PNG_USER_WIDTH_MAX and PNG_USER_HEIGHT_MAX, although this document said +that it could be used to override them. Now this function will reduce or +increase the limits. + B. Changes to the build and configuration of libpng Details of internal changes to the library code can be found in the CHANGES @@ -4081,13 +4424,13 @@ Other rules can be inferred by inspecting the libpng source. XIV. Y2K Compliance in libpng -February 3, 2011 +July 7, 2011 Since the PNG Development group is an ad-hoc body, we can't make an official declaration. This is your unofficial assurance that libpng from version 0.71 and -upward through 1.5.1 are Y2K compliant. It is my belief that earlier +upward through 1.5.4 are Y2K compliant. It is my belief that earlier versions were also Y2K compliant. Libpng only has three year fields. One is a 2-byte unsigned integer that diff --git a/src/3rdparty/libpng/libpng.3 b/src/3rdparty/libpng/libpng.3 index ecc4277..04518ca 100644 --- a/src/3rdparty/libpng/libpng.3 +++ b/src/3rdparty/libpng/libpng.3 @@ -1,6 +1,6 @@ -.TH LIBPNG 3 "February 3, 2011" +.TH LIBPNG 3 "July 7, 2011" .SH NAME -libpng \- Portable Network Graphics (PNG) Reference Library 1.5.1 +libpng \- Portable Network Graphics (PNG) Reference Library 1.5.4 .SH SYNOPSIS \fI\fB @@ -512,6 +512,14 @@ libpng \- Portable Network Graphics (PNG) Reference Library 1.5.1 \fI\fB +\fBvoid png_set_alpha_mode (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fImode\fP\fB, double \fIoutput_gamma\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_alpha_mode_fixed (png_structp \fP\fIpng_ptr\fP\fB, int \fP\fImode\fP\fB, png_fixed_point \fIoutput_gamma\fP\fB);\fP + +\fI\fB + \fBvoid png_set_background (png_structp \fP\fIpng_ptr\fP\fB, png_color_16p \fP\fIbackground_color\fP\fB, int \fP\fIbackground_gamma_code\fP\fB, int \fP\fIneed_expand\fP\fB, double \fIbackground_gamma\fP\fB);\fP \fI\fB @@ -576,6 +584,10 @@ libpng \- Portable Network Graphics (PNG) Reference Library 1.5.1 \fI\fB +\fBvoid png_set_expand_16 (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + \fBvoid png_set_expand_gray_1_2_4_to_8 (png_structp \fIpng_ptr\fP\fB);\fP \fI\fB @@ -752,6 +764,10 @@ libpng \- Portable Network Graphics (PNG) Reference Library 1.5.1 \fI\fB +\fBvoid png_set_scale_16 (png_structp \fIpng_ptr\fP\fB);\fP + +\fI\fB + \fBvoid png_set_shift (png_structp \fP\fIpng_ptr\fP\fB, png_color_8p \fItrue_bits\fP\fB);\fP \fI\fB @@ -796,6 +812,26 @@ libpng \- Portable Network Graphics (PNG) Reference Library 1.5.1 \fI\fB +\fBvoid png_set_text_compression_level (png_structp \fP\fIpng_ptr\fP\fB, int \fIlevel\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_text_compression_mem_level (png_structp \fP\fIpng_ptr\fP\fB, int \fImem_level\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_text_compression_strategy (png_structp \fP\fIpng_ptr\fP\fB, int \fIstrategy\fP\fB);\fP + +\fI\fB + +\fBvoid png_set_text_compression_window_bits (png_structp \fP\fIpng_ptr\fP\fB, int \fIwindow_bits\fP\fB);\fP + +\fI\fB + +\fBvoid \fP\fIpng_set_text_compression_method\fP\fB, (png_structp \fP\fIpng_ptr\fP\fB, int \fImethod)\fP\fB);\fP + +\fI\fB + \fBvoid png_set_tIME (png_structp \fP\fIpng_ptr\fP\fB, png_infop \fP\fIinfo_ptr\fP\fB, png_timep \fImod_time\fP\fB);\fP \fI\fB @@ -919,7 +955,7 @@ Following is a copy of the libpng-manual.txt file that accompanies libpng. .SH LIBPNG.TXT libpng-manual.txt - A description on how to use and modify libpng - libpng version 1.5.1 - February 3, 2011 + libpng version 1.5.4 - July 7, 2011 Updated and distributed by Glenn Randers-Pehrson <glennrp at users.sourceforge.net> Copyright (c) 1998-2011 Glenn Randers-Pehrson @@ -930,7 +966,7 @@ libpng-manual.txt - A description on how to use and modify libpng Based on: - libpng versions 0.97, January 1998, through 1.5.1 - February 3, 2011 + libpng versions 0.97, January 1998, through 1.5.4 - July 7, 2011 Updated and distributed by Glenn Randers-Pehrson Copyright (c) 1998-2011 Glenn Randers-Pehrson @@ -1117,9 +1153,9 @@ reconfiguration of pnglibconf.h. To reconfigure pnglibconf.h it must either be rebuilt from scripts/pnglibconf.dfa using awk or it must be edited by hand. Hand editing is achieved by copying scripts/pnglibconf.h.prebuilt and changing -the lines defining the supported features, paying very close attention to the -'option' information in scripts/pnglibconf.dfa that describes those features and -their requirements. This is easy to get wrong. +the lines defining the supported features, paying very close attention to +the 'option' information in scripts/pnglibconf.dfa that describes those +features and their requirements. This is easy to get wrong. B. Configuration using DFA_XTRA @@ -1267,21 +1303,12 @@ create the structure, so your application should check for that. return (ERROR); } - png_infop end_info = png_create_info_struct(png_ptr); - - if (!end_info) - { - png_destroy_read_struct(&png_ptr, &info_ptr, - (png_infopp)NULL); - return (ERROR); - } - If you want to use your own memory allocation routines, use a libpng that was built with PNG_USER_MEM_SUPPORTED defined, and use png_create_read_struct_2() instead of png_create_read_struct(): png_structp png_ptr = png_create_read_struct_2 - (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, + (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr, user_error_fn, user_warning_fn, (png_voidp) user_mem_ptr, user_malloc_fn, user_free_fn); @@ -1293,7 +1320,7 @@ handling and memory alloc/free functions. When libpng encounters an error, it expects to longjmp back to your routine. Therefore, you will need to call setjmp and pass your png_jmpbuf(png_ptr). If you read the file from different -routines, you will need to update the jmpbuf field every time you enter +routines, you will need to update the longjmp buffer every time you enter a new routine that will call a png_*() function. See your documentation of setjmp/longjmp for your compiler for more @@ -1311,6 +1338,9 @@ free any memory. return (ERROR); } +Pass (png_infopp)NULL instead of &end_info if you didn't create +an end_info structure. + If you would rather avoid the complexity of setjmp/longjmp issues, you can compile libpng with PNG_NO_SETJMP, in which case errors will result in a call to PNG_ABORT() which defaults to abort(). @@ -1432,6 +1462,19 @@ To inform libpng about your function, use png_set_read_status_fn(png_ptr, read_row_callback); +When this function is called the row has already been completely processed and +the 'row' and 'pass' refer to the next row to be handled. For the +non-interlaced case the row that was just handled is simply one less than the +passed in row number, and pass will always be 0. For the interlaced case the +same applies unless the row value is 0, in which case the row just handled was +the last one from one of the preceding passes. Because interlacing may skip a +pass you cannot be sure that the preceding pass is just 'pass-1', if you really +need to know what the last pass is record (row,pass) from the callback and use +the last recorded value each time. + +As with the user transform you can find the output row using the +PNG_ROW_FROM_PASS_ROW macro. + .SS Unknown-chunk handling Now you get to set the way the library processes unknown chunks in the @@ -1509,7 +1552,7 @@ large as 2^31-1 (0x7fffffff), or about 2.147 billion rows and columns. Since very few applications really need to process such large images, we have imposed an arbitrary 1-million limit on rows and columns. Larger images will be rejected immediately with a png_error() call. If -you wish to override this limit, you can use +you wish to change this limit, you can use png_set_user_limits(png_ptr, width_max, height_max); @@ -1519,6 +1562,10 @@ anyway because of potential buffer overflow conditions). You should put this statement after you create the PNG structure and before calling png_read_info(), png_read_png(), or png_process_data(). + +When writing a PNG datastream, put this statement before calling +png_write_info() or png_write_png(). + If you need to retrieve the limits that are being applied, use width_max = png_get_user_width_max(png_ptr); @@ -1549,6 +1596,234 @@ and you can retrieve the limit with Any chunks that would cause either of these limits to be exceeded will be ignored. +.SS Information about your system + +If you intend to display the PNG or to incorporate it in other image data you +need to tell libpng information about your display or drawing surface so that +libpng can convert the values in the image to match the display. + +From libpng-1.5.4 this information can be set before reading the PNG file +header. In earlier versions png_set_gamma() existed but behaved incorrectly if +called before the PNG file header had been read and png_set_alpha_mode() did not +exist. + +If you need to support versions prior to libpng-1.5.4 test the version number +and follow the procedures described in the appropriate manual page. + +You give libpng the encoding expected by your system expressed as a 'gamma' +value. You can also specify a default encoding for the PNG file in +case the required information is missing from the file. By default libpng +assumes that the PNG data matches your system, to keep this default call: + + png_set_gamma(png_ptr, screen_gamma, 1/screen_gamma/*file gamma*/); + +or you can use the fixed point equivalent: + + png_set_gamma_fixed(png_ptr, PNG_FP_1*screen_gamma, PNG_FP_1/screen_gamma); + +If you don't know the gamma for you system it is probably 2.2 - a good +approximation to the IEC standard for display systems (sRGB). If images are +too contrasty or washed out you got the value wrong - check your system +documentation! + +Many systems permit the system gamma to be changed via a lookup table in the +display driver, a few systems, including older Macs, change the response by +default. As of 1.5.4 three special values are available to handle common +situations: + + PNG_DEFAULT_sRGB: Indicates that the system conforms to the IEC 61966-2-1 + standard. This matches almost all systems. + PNG_GAMMA_MAC_18: Indicates that the system is an older (pre Mac OS 10.6) + Apple Macintosh system with the default settings. + PNG_GAMMA_LINEAR: Just the fixed point value for 1.0 - indicates that the + system expects data with no gamma encoding. + +You would use the linear (unencoded) value if you need to process the pixel +values further because this avoids the need to decode and reencode each +component value whenever arithmetic is performed. A lot of graphics software +uses linear values for this reason, often with higher precision component values +to preserve overall accuracy. + +The second thing you may need to tell libpng about is how your system handles +alpha channel information. Some, but not all, PNG files contain an alpha +channel. To display these files correctly you need to compose the data onto a +suitable background, as described in the PNG specification. + +Libpng only supports composing onto a single color (using png_set_background; +see below.) Otherwise you must do the composition yourself and, in this case, +you may need to call png_set_alpha_mode: + + png_set_alpha_mode(png_ptr, mode, screen_gamma); + +The screen_gamma value is the same as the argument to png_set_gamma, however how +it affects the output depends on the mode. png_set_alpha_mode() sets the file +gamma default to 1/screen_gamma, so normally you don't need to call +png_set_gamma. If you need different defaults call png_set_gamma() before +png_set_alpha_mode() - if you call it after it will override the settings made +by png_set_alpha_mode(). + +The mode is as follows: + + PNG_ALPHA_PNG: The data is encoded according to the PNG specification. Red, +green and blue, or gray, components are gamma encoded color +values and are not premultiplied by the alpha value. The +alpha value is a linear measure of the contribution of the +pixel to the corresponding final output pixel. + +You should normally use this format if you intend to perform +color correction on the color values; most, maybe all, color +correction software has no handling for the alpha channel and, +anyway, the math to handle pre-multiplied component values is +unnecessarily complex. + +Before you do any arithmetic on the component values you need +to remove the gamma encoding and multiply out the alpha +channel. See the PNG specification for more detail. It is +important to note that when an image with an alpha channel is +scaled, linear encoded, pre-multiplied component values must +be used! + +The remaining modes assume you don't need to do any further color correction or +that if you do your color correction software knows all about alpha (it +probably doesn't!) + + PNG_ALPHA_STANDARD: The data libpng produces is encoded in the standard way +assumed by most correctly written graphics software. +The gamma encoding will be removed by libpng and the +linear component values will be pre-multiplied by the +alpha channel. + +With this format the final image must be re-encoded to +match the display gamma before the image is displayed. +If your system doesn't do that, yet still seems to +perform arithmetic on the pixels without decoding them, +it is broken - check out the modes below. + +With PNG_ALPHA_STANDARD libpng always produces linear +component values, whatever screen_gamma you supply. The +screen_gamma value is, however, used as a default for +the file gamma if the PNG file has no gamma information. + +If you call png_set_gamma() after png_set_alpha_mode() you +will override the linear encoding. Instead the +pre-multiplied pixel values will be gamma encoded but +the alpha channel will still be linear. This may +actually match the requirements of some broken software, +but it is unlikely. + +While linear 8-bit data is often used it has +insufficient precision for any image with a reasonable +dynamic range. To avoid problems, and if your software +supports it, use png_set_expand_16() to force all +components to 16 bits. + + PNG_ALPHA_OPTIMIZED: This mode is the same as PNG_ALPHA_STANDARD except that +completely opaque pixels are gamma encoded according to +the screen_gamma value. Pixels with alpha less than 1.0 +will still have linear components. + +Use this format if you have control over your +compositing software and do don't do other arithmetic +(such as scaling) on the data you get from libpng. Your +compositing software can simply copy opaque pixels to +the output but still has linear values for the +non-opaque pixels. + +In normal compositing, where the alpha channel encodes +partial pixel coverage (as opposed to broad area +translucency), the inaccuracies of the 8-bit +representation of non-opaque pixels are irrelevant. + +You can also try this format if your software is broken; +it might look better. + + PNG_ALPHA_BROKEN: This is PNG_ALPHA_STANDARD however all component values, +including the alpha channel are gamma encoded. This is +an appropriate format to try if your software, or more +likely hardware, is totally broken: if it performs +linear arithmetic directly on gamma encoded values. + +In most cases of broken software or hardware the bug in the final display +manifests as a subtle halo around composited parts of the image. You may not +even perceive this as a halo; the composited part of the image may simply appear +separate from the background, as though it had been cut out of paper and pasted +on afterward. + +If you don't have to deal with bugs in software or hardware, or if you can fix +them, there are three recommended ways of using png_set_alpha_mode(): + + png_set_alpha_mode(png_ptr, PNG_ALPHA_PNG, + screen_gamma); + +You can do color correction on the result (libpng does not currently +support color correction internally.) When you handle the alpha channel +you need to undo the gamma encoding and multiply out the alpha. + + png_set_alpha_mode(png_ptr, PNG_ALPHA_STANDARD, + screen_gamma); + png_set_expand_16(png_ptr); + +If you are using the high level interface don't call png_set_expand_16(); +instead pass PNG_TRANSFORM_EXPAND_16 to the interface. + +With this mode you can't do color correction, but you can do arithmetic, +including composition and scaling, on the data without further processing. + + png_set_alpha_mode(png_ptr, PNG_ALPHA_OPTIMIZED, + screen_gamma); + +You can avoid the expansion to 16-bit components with this mode, but you +lose the ability to scale the image or perform other linear arithmetic. +All you can do is compose the result onto a matching output. Since this +mode is libpng specific you also need to write your own composition +software. + +If you don't need, or can't handle, the alpha channel you can call +png_set_background() to remove it by compositing against a fixed color. Don't +call png_set_strip_alpha() to do this - it will leave spurious pixel values in +transparent parts of this image. + + png_set_background(png_ptr, &background_color, + PNG_BACKGROUND_GAMMA_SCREEN, 0, 1); + +The background_color is an RGB or grayscale value according to the data format +libpng will produce for you. Because you don't yet know the format of the PNG +file if you call png_set_background at this point you must arrange for the +format produced by libpng to always have 8-bit or 16-bit components and then +store the color as an 8-bit or 16-bit color as appropriate. The color contains +separate gray and RGB component values, so you can let libpng produce gray or +RGB output according to the input format, but low bit depth grayscale images +must always be converted to at least 8-bit format. (Even low low bit depth +grayscale images can't have an alpha channel they can have a transparent +color!) + +You set the transforms you need later, either as flags to the high level +interface or libpng API calls for the low level interface. For reference the +settings and API calls required are: + +8-bit values: + PNG_TRANSFORM_SCALE_16 | PNG_EXPAND + png_set_expand(png_ptr); png_set_scale_16(png_ptr); + + If you must get exactly the same inaccurate results + produced by default in versions prior to libpng-1.5.4, + use PNG_TRANSFORM_STRIP_16 and png_set_strip_16(png_ptr) + instead. + +16-bit values: + PNG_TRANSFORM_EXPAND_16 + png_set_expand_16(png_ptr); + +In either case palette image data will be expanded to RGB. If you just want +color data you can add PNG_TRANSFORM_GRAY_TO_RGB or png_set_gray_to_rgb(png_ptr) +to the list. + +Calling png_set_background before the PNG file header is read will not work +prior to libpng-1.5.4. Because the failure may result in unexpected warnings or +errors it is therefore much safer to call png_set_background after the head has +been read. Unfortunately this means that prior to libpng-1.5.4 it cannot be +used with the high level interface. + .SS The high-level read interface At this point there are two ways to proceed; through the high-level @@ -1558,8 +1833,10 @@ the entire image into memory, and (b) the input transformations you want to do are limited to the following set: PNG_TRANSFORM_IDENTITY No transformation - PNG_TRANSFORM_STRIP_16 Strip 16-bit samples to - 8 bits + PNG_TRANSFORM_SCALE_16 Strip 16-bit samples to + 8-bit accurately + PNG_TRANSFORM_STRIP_16 Chop 16-bit samples to + 8-bit less accurately PNG_TRANSFORM_STRIP_ALPHA Discard the alpha channel PNG_TRANSFORM_PACKING Expand 1, 2 and 4-bit samples to bytes @@ -1578,6 +1855,7 @@ you want to do are limited to the following set: PNG_TRANSFORM_SWAP_ENDIAN Byte-swap 16-bit samples PNG_TRANSFORM_GRAY_TO_RGB Expand grayscale samples to RGB (or GA to RGBA) + PNG_TRANSFORM_EXPAND_16 Expand samples to 16 bits (This excludes setting a background color, doing gamma transformation, quantizing, and setting filler.) If this is the case, simply do this: @@ -1646,6 +1924,22 @@ call to png_read_info(). This will process all chunks up to but not including the image data. +This also copies some of the data from the PNG file into the decode structure +for use in later transformations. Important information copied in is: + +1) The PNG file gamma from the gAMA chunk. This overwrites the default value +provided by an earlier call to png_set_gamma or png_set_alpha_mode. + +2) Prior to libpng-1.5.4 the background color from a bKGd chunk. This +damages the information provided by an earlier call to png_set_background +resulting in expected behavior. Libpng-1.5.4 no longer does this. + +3) The number of significant bits in each component value. Libpng uses this to +optimize gamma handling by reducing the internal lookup table sizes. + +4) The transparent color information from a tRNS chunk. This can be modified by +a later call to png_set_tRNS. + .SS Querying the info structure Functions are used to get the information from the info_ptr once it @@ -1988,7 +2282,7 @@ forms: 72 dpi is stored as 0.28346 pixels/meter, and when this is retrieved it is 71.9988 dpi, so be sure to round the returned value appropriately - if you want to display a reasonable-looking result. + if you want to display a reasonable-looking result. The data from the oFFs chunk can be retrieved in several convenient forms: @@ -2009,7 +2303,7 @@ forms: converted to microns and back without some loss of precision. -For more information, see the png_info definition in png.h and the +For more information, see the PNG specification for chunk contents. Be careful with trusting rowbytes, as some of the transformations could increase the space needed to hold a row (expand, filler, gray_to_rgb, etc.). @@ -2044,17 +2338,20 @@ to handle any special transformations of the image data. The various ways to transform the data will be described in the order that they should occur. This is important, as some of these change the color type and/or bit depth of the data, and some others only work on -certain color types and bit depths. Even though each transformation -checks to see if it has data that it can do something with, you should -make sure to only enable a transformation if it will be valid for the -data. For example, don't swap red and blue on grayscale data. +certain color types and bit depths. + +Transformations you request are ignored if they don't have any meaning for a +particular input data format. However some transformations can have an effect +as a result of a previous transformation. If you specify a contradictory set of +transformations, for example both adding and removing the alpha channel, you +cannot predict the final result. -The colors used for the background and transparency values should be -supplied in the same format/depth as the current image data. They -are stored in the same format/depth as the image data in a bKGD or tRNS -chunk, so this is what libpng expects for this data. The colors are -transformed to keep in sync with the image data when an application -calls the png_read_update_info() routine (see below). +The color used for the transparency values should be supplied in the same +format/depth as the current image data. It is stored in the same format/depth +as the image data in a tRNS chunk, so this is what libpng expects for this data. + +The color used for the background value depends on the need_expand argument as +described below. Data will be decoded into the supplied row buffers packed into bytes unless the library has been told to transform it into another format. @@ -2064,12 +2361,12 @@ byte, unless png_set_packing() is called. 8-bit RGB data will be stored in RGB RGB RGB format unless png_set_filler() or png_set_add_alpha() is called to insert filler bytes, either before or after each RGB triplet. 16-bit RGB data will be returned RRGGBB RRGGBB, with the most significant -byte of the color value first, unless png_set_strip_16() is called to +byte of the color value first, unless png_set_scale_16() is called to transform it to regular RGB RGB triplets, or png_set_filler() or png_set_add alpha() is called to insert filler bytes, either before or after each RRGGBB triplet. Similarly, 8-bit or 16-bit grayscale data can -be modified with -png_set_filler(), png_set_add_alpha(), or png_set_strip_16(). +be modified with png_set_filler(), png_set_add_alpha(), png_set_strip_16(), +or png_set_scale_16(). The following code transforms grayscale images of less than 8 to 8 bits, changes paletted images to RGB, and adds a full alpha channel if there is @@ -2080,13 +2377,13 @@ viewing application that wishes to treat all images in the same way. if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); - if (color_type == PNG_COLOR_TYPE_GRAY && - bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); - if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png_ptr); -These three functions are actually aliases for png_set_expand(), added + if (color_type == PNG_COLOR_TYPE_GRAY && + bit_depth < 8) png_set_expand_gray_1_2_4_to_8(png_ptr); + +The first two functions are actually aliases for png_set_expand(), added in libpng version 1.0.4, with the function names expanded to improve code readability. In some future version they may actually do different things. @@ -2094,56 +2391,84 @@ things. As of libpng version 1.2.9, png_set_expand_gray_1_2_4_to_8() was added. It expands the sample depth without changing tRNS to alpha. -As of libpng version 1.5.1, not all possible expansions are supported. +As of libpng version 1.5.2, png_set_expand_16() was added. It behaves as +png_set_expand(), however, the resultant channels have 16 bits rather than 8. +Use this when the output color or gray channels are made linear to avoid fairly +severe accuracy loss. + + if (bit_depth < 16) + png_set_expand_16(png_ptr); + +PNG can have files with 16 bits per channel. If you only can handle +8 bits per channel, this will strip the pixels down to 8-bit. + + if (bit_depth == 16) + png_set_scale_16(png_ptr); + +If you need to process the alpha channel on the image separately from the image +data (for example if you convert it to a bitmap mask) it is possible to have +libpng strip the channel leaving just RGB or gray data: + + if (color_type & PNG_COLOR_MASK_ALPHA) + png_set_strip_alpha(png_ptr); + +If you strip the alpha channel you need to find some other way of dealing with +the information. If, instead, you want to convert the image to an opaque +version with no alpha channel use png_set_background; see below. + +As of libpng version 1.5.2, almost all useful expansions are supported, the +major ommissions are conversion of grayscale to indexed images (which can be +done trivially in the application) and conversion of indexed to grayscale (which +can be done by a trivial manipulation of the palette.) In the following table, the 01 means grayscale with depth<8, 31 means indexed with depth<8, other numerals represent the color type, "T" means the tRNS chunk is present, A means an alpha channel is present, and O means tRNS or alpha is present but all pixels in the image are opaque. - FROM 01 31 0 0T 0O 2 2T 2O 3 3T 3O 4A 4O 6A 6O + FROM 01 31 0 0T 0O 2 2T 2O 3 3T 3O 4A 4O 6A 6O TO - 01 - - 31 - - 0 1 - - 0T - - 0O - - 2 GX - - 2T - - 2O - - 3 1 - - 3T - - 3O - - 4A T - - 4O - - 6A GX TX TX - - 6O GX TX - + 01 - [G] - - - - - - - - - - - - - + 31 [Q] Q [Q] [Q] [Q] Q Q Q Q Q Q [Q] [Q] Q Q + 0 1 G + . . G G G G G G B B GB GB + 0T lt Gt t + . Gt G G Gt G G Bt Bt GBt GBt + 0O lt Gt t . + Gt Gt G Gt Gt G Bt Bt GBt GBt + 2 C P C C C + . . C - - CB CB B B + 2T Ct - Ct C C t + t - - - CBt CBt Bt Bt + 2O Ct - Ct C C t t + - - - CBt CBt Bt Bt + 3 [Q] p [Q] [Q] [Q] Q Q Q + . . [Q] [Q] Q Q + 3T [Qt] p [Qt][Q] [Q] Qt Qt Qt t + t [Qt][Qt] Qt Qt + 3O [Qt] p [Qt][Q] [Q] Qt Qt Qt t t + [Qt][Qt] Qt Qt + 4A lA G A T T GA GT GT GA GT GT + BA G GBA + 4O lA GBA A T T GA GT GT GA GT GT BA + GBA G + 6A CA PA CA C C A T tT PA P P C CBA + BA + 6O CA PBA CA C C A tT T PA P P CBA C BA + Within the matrix, + "+" identifies entries where 'from' and 'to' are the same. "-" means the transformation is not supported. + "." means nothing is necessary (a tRNS chunk can just be ignored). + "t" means the transformation is obtained by png_set_tRNS. + "A" means the transformation is obtained by png_set_add_alpha(). "X" means the transformation is obtained by png_set_expand(). "1" means the transformation is obtained by - png_set_expand_gray_1_2_4_to_8 - "G" means the transformation is obtained by - png_set_gray_to_rgb(). + png_set_expand_gray_1_2_4_to_8() (and by png_set_expand() if there + is no transparency in the original or the final format). + "C" means the transformation is obtained by png_set_gray_to_rgb(). + "G" means the transformation is obtained by png_set_rgb_to_gray(). "P" means the transformation is obtained by png_set_expand_palette_to_rgb(). - "T" means the transformation is obtained by - png_set_tRNS_to_alpha(). - -PNG can have files with 16 bits per channel. If you only can handle -8 bits per channel, this will strip the pixels down to 8 bit. - - if (bit_depth == 16) - png_set_strip_16(png_ptr); - -If, for some reason, you don't need the alpha channel on an image, -and you want to remove it rather than combining it with the background -(but the image author certainly had in mind that you *would* combine -it with the background, so that's what you should probably do): - - if (color_type & PNG_COLOR_MASK_ALPHA) - png_set_strip_alpha(png_ptr); + "p" means the transformation is obtained by png_set_packing(). + "Q" means the transformation is obtained by png_set_quantize(). + "T" means the transformation is obtained by png_set_tRNS_to_alpha(). + "B" means the transformation is obtained by png_set_background(), or + png_strip_alpha(). + +When an entry has multiple transforms listed all are required to cause the +right overall transformation. When two transforms are separated by a comma +either will do the job. When transforms are enclosed in [] the transform should +do the job but this is currently unimplemented - a different format will result +if the suggested transformations are used. In PNG files, the alpha channel in an image is the level of opacity. If you need the alpha channel in an image to @@ -2222,8 +2547,8 @@ with alpha. if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGB_ALPHA) - png_set_rgb_to_gray_fixed(png_ptr, error_action, - int red_weight, int green_weight); + png_set_rgb_to_gray(png_ptr, error_action, double red_weight, + double green_weight); error_action = 1: silently do the conversion @@ -2236,122 +2561,89 @@ with alpha. image has any pixel where red != green or red != blue - red_weight: weight of red component times 100000 + red_weight: weight of red component - green_weight: weight of green component times 100000 + green_weight: weight of green component If either weight is negative, default - weights (21268, 71514) are used. + weights are used. + +In the corresponding fixed point API the red_weight and green_weight values are +simply scaled by 100,000: + + png_set_rgb_to_gray(png_ptr, error_action, png_fixed_point red_weight, + png_fixed_point green_weight); If you have set error_action = 1 or 2, you can later check whether the image really was gray, after processing the image rows, with the png_get_rgb_to_gray_status(png_ptr) function. It will return a png_byte that is zero if the image was gray or -1 if there were any non-gray pixels. bKGD and sBIT data +1 if there were any non-gray pixels. Background and sBIT data will be silently converted to grayscale, using the green channel -data, regardless of the error_action setting. +data for sBIT, regardless of the error_action setting. -With red_weight+green_weight<=100000, -the normalized graylevel is computed: +The default values come from the PNG file cHRM chunk if present, otherwise the +defaults correspond to the ITU-R recommendation 709, and also the sRGB color +space, as recommended in the Charles Poynton's Colour FAQ, +<http://www.poynton.com/>, in section 9: - int rw = red_weight * 65536; - int gw = green_weight * 65536; - int bw = 65536 - (rw + gw); - gray = (rw*red + gw*green + bw*blue)/65536; - -The default values approximate those recommended in the Charles -Poynton's Color FAQ, <http://www.inforamp.net/~poynton/> -Copyright (c) 1998-01-04 Charles Poynton <poynton at inforamp.net> + <http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC9> Y = 0.212671 * R + 0.715160 * G + 0.072169 * B -Libpng approximates this with integers scaled by 32768: - - Y = (6968 * R + 23434 * G + 2366 * B)/32768 - The calculation is done in a linear colorspace, if the image gamma can be determined. -If you have a grayscale and you are using png_set_expand_depth(), -png_set_expand(), or png_set_gray_to_rgb to change to truecolor or to -a higher bit-depth, you must either supply the background color as a gray -value at the original file bit-depth (need_expand = 1) or else supply the -background color as an RGB triplet at the final, expanded bit depth -(need_expand = 0). Similarly, if you are reading a paletted image, you -must either supply the background color as a palette index (need_expand = 1) -or as an RGB triplet that may or may not be in the palette (need_expand = 0). +The png_set_background() function has been described already, it tells libpng to +composite images with alpha or simple transparency against the supplied +background color. For compatibility with versions of libpng earlier than +libpng-1.5.4 it is recommended that you call the function after reading the file +header, even if you don't want to use the color in a bKGD chunk, if one exists. + +If the PNG file contains a bKGD chunk (PNG_INFO_bKGD valid), +you may use this color, or supply another color more suitable for +the current display (e.g., the background color from a web page). You +need to tell libpng how the color is represented, both the format of the +component values in the color (the number of bits) and the gamme encoding of the +color. The function takes two arguments, background_gamma_mode and need_expand +to convey this information, however only two combinations are like to be useful: png_color_16 my_background; png_color_16p image_background; if (png_get_bKGD(png_ptr, info_ptr, &image_background)) png_set_background(png_ptr, image_background, - PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); + PNG_BACKGROUND_GAMMA_FILE, 1/*needs to be expanded*/, 1); else png_set_background(png_ptr, &my_background, - PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); + PNG_BACKGROUND_GAMMA_SCREEN, 0/*do not expand*/, 1); -The png_set_background() function tells libpng to composite images -with alpha or simple transparency against the supplied background -color. If the PNG file contains a bKGD chunk (PNG_INFO_bKGD valid), -you may use this color, or supply another color more suitable for -the current display (e.g., the background color from a web page). You -need to tell libpng whether the color is in the gamma space of the -display (PNG_BACKGROUND_GAMMA_SCREEN for colors you supply), the file -(PNG_BACKGROUND_GAMMA_FILE for colors from the bKGD chunk), or one -that is neither of these gammas (PNG_BACKGROUND_GAMMA_UNIQUE - I don't -know why anyone would use this, but it's here). - -To properly display PNG images on any kind of system, the application needs -to know what the display gamma is. Ideally, the user will know this, and -the application will allow them to set it. One method of allowing the user -to set the display gamma separately for each system is to check for a -SCREEN_GAMMA or DISPLAY_GAMMA environment variable, which will hopefully be -correctly set. - -Note that display_gamma is the overall gamma correction required to produce -pleasing results, which depends on the lighting conditions in the surrounding -environment. In a dim or brightly lit room, no compensation other than -the physical gamma exponent of the monitor is needed, while in a dark room -a slightly smaller exponent is better. - - double gamma, screen_gamma; - - if (/* We have a user-defined screen - gamma value */) - { - screen_gamma = user_defined_screen_gamma; - } - /* One way that applications can share the same - screen gamma value */ - else if ((gamma_str = getenv("SCREEN_GAMMA")) - != NULL) - { - screen_gamma = (double)atof(gamma_str); - } +The second call was described above - my_background is in the format of the +final, display, output produced by libpng. Because you now know the format of +the PNG it is possible to avoid the need to choose either 8-bit or 16-bit +output and to retain palette images (the palette colors will be modified +appropriately and the tRNS chunk removed.) However, if you are doing this, +take great care not to ask for transformations without checking first that +they apply! - /* If we don't have another value */ - else - { - screen_gamma = 2.2; /* A good guess for a - PC monitor in a bright office or a dim room */ +In the first call the background color has the original bit depth and color type +of the PNG file. So, for palette images the color is supplied as a palette +index and for low bit greyscale images the color is a reduced bit value in +image_background->gray. - screen_gamma = 2.0; /* A good guess for a - PC monitor in a dark room */ +If you didn't call png_set_gamma() before reading the file header, for example +if you need your code to remain compatible with older versions of libpng prior +to libpng-1.5.4, this is the place to call it. - screen_gamma = 1.7 or 1.0; /* A good - guess for Mac systems */ - } +Do not call it if you called png_set_alpha_mode(); doing so will damage the +settings put in place by png_set_alpha_mode(). (If png_set_alpha_mode() is +supported then you can certainly do png_set_gamma() before reading the PNG +header.) -The functions png_set_gamma() and its fixed point equivalent -png_set_gamma_fixed() handle gamma transformations of the data. -Pass both the file gamma and the current screen_gamma. If the file does -not have a gamma value, you can pass one anyway if you have an idea what -it is (usually 0.45455 is a good guess for GIF images on PCs). Note -that file gammas are inverted from screen gammas. See the discussions -on gamma in the PNG specification for an excellent description of what -gamma is, and why all applications should support it. It is strongly -recommended that PNG viewers support gamma correction. +This API unconditionally sets the screen and file gamma values, so it will +override the value in the PNG file unless it is called before the PNG file +reading starts. For this reason you must always call it with the PNG file +value when you call it in this position: if (png_get_gAMA(png_ptr, info_ptr, &file_gamma)) png_set_gamma(png_ptr, screen_gamma, file_gamma); @@ -2407,7 +2699,7 @@ This function can also be used to invert grayscale and gray-alpha images: color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_invert_mono(png_ptr); -PNG files store 16 bit pixels in network byte order (big-endian, +PNG files store 16-bit pixels in network byte order (big-endian, ie. most significant bits first). This code changes the storage to the other way (little-endian, i.e. least significant bits first, the way PCs store them): @@ -2430,7 +2722,7 @@ with You must supply the function - void read_transform_fn(png_structp png_ptr, row_info_ptr + void read_transform_fn(png_structp png_ptr, png_row_infop row_info, png_bytep data) See pngtest.c for a working example. Your function will be called @@ -2449,6 +2741,14 @@ supported if user transforms are supported, secondly they may well return unexpected results unless the row is actually being processed at the moment they are called. +With interlaced +images the value returned is the row in the input sub-image image. Use +PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to +find the output pixel (x,y) given an interlaced sub-image pixel (row,col,pass). + +The discussion of interlace handling above contains more information on how to +use these values. + You can also set up a pointer to a user structure for use by your callback function, and you can inform libpng that your transform function will change the number of channels or bit depth with the @@ -2691,15 +2991,39 @@ low-level interface, you can finish reading the file. If you are interested in comments or time, which may be stored either before or after the image data, you should pass the separate png_info struct if you want to keep the comments from before and after the image -separate. If you are not interested, you can pass NULL. +separate. + + png_infop end_info = png_create_info_struct(png_ptr); + + if (!end_info) + { + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + return (ERROR); + } png_read_end(png_ptr, end_info); +If you are not interested, you should still call png_read_end() +but you can pass NULL, avoiding the need to create an end_info structure. + + png_read_end(png_ptr, (png_infop)NULL); + +If you don't call png_read_end(), then your file pointer will be +left pointing to the first chunk after the last IDAT, which is probably +not what you want if you expect to read something beyond the end of +the PNG datastream. + When you are done, you can free all memory allocated by libpng like this: png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); +or, if you didn't create an end_info structure, + + png_destroy_read_struct(&png_ptr, &info_ptr, + (png_infopp)NULL); + It is also possible to individually free the info_ptr members that point to libpng-allocated storage with the following function: @@ -3102,6 +3426,20 @@ To inform libpng about your function, use png_set_write_status_fn(png_ptr, write_row_callback); +When this function is called the row has already been completely processed and +it has also been written out. The 'row' and 'pass' refer to the next row to be +handled. For the +non-interlaced case the row that was just handled is simply one less than the +passed in row number, and pass will always be 0. For the interlaced case the +same applies unless the row value is 0, in which case the row just handled was +the last one from one of the preceding passes. Because interlacing may skip a +pass you cannot be sure that the preceding pass is just 'pass-1', if you really +need to know what the last pass is record (row,pass) from the callback and use +the last recorded value each time. + +As with the user transform you can find the output row using the +PNG_ROW_FROM_PASS_ROW macro. + You now have the option of modifying how the compression library will run. The following functions are mainly for testing, but may be useful in some cases, like if you need to write PNG files extremely fast and @@ -3146,11 +3484,13 @@ which changes how much time zlib spends on trying to compress the image data. See the Compression Library (zlib.h and algorithm.txt, distributed with zlib) for details on the compression levels. - /* set the zlib compression level */ + #include zlib.h + + /* Set the zlib compression level */ png_set_compression_level(png_ptr, Z_BEST_COMPRESSION); - /* set other zlib parameters */ + /* Set other zlib parameters for compressing IDAT */ png_set_compression_mem_level(png_ptr, 8); png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY); @@ -3158,7 +3498,15 @@ with zlib) for details on the compression levels. png_set_compression_method(png_ptr, 8); png_set_compression_buffer_size(png_ptr, 8192) -extern PNG_EXPORT(void,png_set_zbuf_size) + /* Set zlib parameters for text compression + * If you don't call these, the parameters + * fall back on those defined for IDAT chunks + */ + png_set_text_compression_mem_level(png_ptr, 8); + png_set_text_compression_strategy(png_ptr, + Z_DEFAULT_STRATEGY); + png_set_text_compression_window_bits(png_ptr, 15); + png_set_text_compression_method(png_ptr, 8); .SS Setting the contents of info for output @@ -3664,7 +4012,7 @@ is required by PNG. png_set_shift(png_ptr, &sig_bit); -PNG files store 16 bit pixels in network byte order (big-endian, +PNG files store 16-bit pixels in network byte order (big-endian, ie. most significant bits first). This code would be used if they are supplied the other way (little-endian, i.e. least significant bits first, the way PCs store them): @@ -3698,8 +4046,8 @@ with You must supply the function - void write_transform_fn(png_structp png_ptr ptr, - row_info_ptr row_info, png_bytep data) + void write_transform_fn(png_structp png_ptr, png_row_infop + row_info, png_bytep data) See pngtest.c for a working example. Your function will be called before any of the other transformations are processed. If supported @@ -3707,9 +4055,15 @@ libpng also supplies an information routine that may be called from your callback: png_get_current_row_number(png_ptr); + png_get_current_pass_number(png_ptr); + +This returns the current row passed to the transform. With interlaced +images the value returned is the row in the input sub-image image. Use +PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to +find the output pixel (x,y) given an interlaced sub-image pixel (row,col,pass). -This returns the current row passed to the transform. Even with interlaced -images the value returned is the row in the final output image. +The discussion of interlace handling above contains more information on how to +use these values. You can also set up a pointer to a user structure for use by your callback function. @@ -4074,7 +4428,7 @@ the simpler ones to get an idea of how they work. Try to find a similar transformation to the one you want to add and copy off of it. More details can be found in the comments inside the code itself. -.SS Configuring for 16 bit platforms +.SS Configuring for 16-bit platforms You will want to look into zconf.h to tell zlib (and thus libpng) that it cannot allocate more then 64K at a time. Even if you can, the memory @@ -4129,6 +4483,7 @@ specify no compression (Z_NO_COMPRESSION = 0), but this would create files larger than just storing the raw bitmap. You can specify the compression level by calling: + #include zlib.h png_set_compression_level(png_ptr, level); Another useful one is to reduce the memory level used by the library. @@ -4139,12 +4494,14 @@ other things, lower levels will result in sections of incompressible data being emitted in smaller stored blocks, with a correspondingly larger relative overhead of up to 15% in the worst case. + #include zlib.h png_set_compression_mem_level(png_ptr, level); The other functions are for configuring zlib. They are not recommended for normal use and may result in writing an invalid PNG file. See zlib.h for more information on what these mean. + #include zlib.h png_set_compression_strategy(png_ptr, strategy); @@ -4542,12 +4899,12 @@ and memset(), respectively. The function png_set_gray_1_2_4_to_8() was removed. It has been deprecated since libpng-1.0.18 and 1.2.9, when it was replaced with png_set_expand_gray_1_2_4_to_8() because the former function also -expanded palette images. +expanded any tRNS chunk to an alpha channel. Macros for png_get_uint_16, png_get_uint_32, and png_get_int_32 were added and are used by default instead of the corresponding functions. Unfortunately, -from libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the +from libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the function) incorrectly returned a value of type png_uint_32. We changed the prototype for png_malloc() from @@ -4577,7 +4934,8 @@ The png_zalloc() function no longer zeroes out the memory that it allocates. Support for dithering was disabled by default in libpng-1.4.0, because -been well tested and doesn't actually "dither". The code was not +it has not been well tested and doesn't actually "dither". +The code was not removed, however, and could be enabled by building libpng with PNG_READ_DITHER_SUPPORTED defined. In libpng-1.4.2, this support was reenabled, but the function was renamed png_set_quantize() to @@ -4590,7 +4948,7 @@ We removed the trailing '.' from the warning and error messages. .SH X. Changes to Libpng from version 1.4.x to 1.5.x -From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the +From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the function) incorrectly returned a value of type png_uint_32. A. Changes that affect users of libpng @@ -4627,7 +4985,8 @@ application code. (It is extremely rare for an application to do this.) Any program that compiled against libpng 1.4 and did not use deprecated features or access internal library structures should compile and work -against libpng 1.5. +against libpng 1.5, except for the change in the prototype for +png_get_iCCP() and png_set_iCCP() API functions mentioned above. libpng 1.5.0 adds PNG_ PASS macros to help in the reading and writing of interlaced images. The macros return the number of rows and columns in @@ -4635,10 +4994,11 @@ each pass and information that can be used to de-interlace and (if absolutely necessary) interlace an image. libpng 1.5.0 adds an API png_longjmp(png_ptr, value). This API calls -the application provided png_longjmp_ptr on the internal, but application +the application-provided png_longjmp_ptr on the internal, but application initialized, jmpbuf. It is provided as a convenience to avoid the need -to use the png_jmpbuf macro, which had the unnecessary side effect of -resetting the internal png_longjmp_ptr value. +initialized, longjmp buffer. It is provided as a convenience to avoid +the need to use the png_jmpbuf macro, which had the unnecessary side +effect of resetting the internal png_longjmp_ptr value. libpng 1.5.0 includes a complete fixed point API. By default this is present along with the corresponding floating point API. In general the @@ -4681,7 +5041,7 @@ reset by pngusr.h or by explicit settings on the compiler command line. These settings may produce compiler warnings or errors in 1.5.0 because of macro redefinition. -From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the +From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the function) incorrectly returned a value of type png_uint_32. libpng 1.5.0 is consistent with the implementation in 1.4.5 and 1.2.x (where the macro did not exist.) @@ -4692,6 +5052,25 @@ PNG_NO_USE_READ_MACROS before including png.h. Notice that this is only supported from 1.5.0 -defining PNG_NO_USE_READ_MACROS prior to 1.5.0 will lead to a link failure. +Prior to libpng-1.5.4, the zlib compressor used the same set of parameters +when compressing the IDAT data and textual data such as zTXt and iCCP. +In libpng-1.5.4 we reinitialized the zlib stream for each type of data. +We added five png_set_text_*() functions for setting the parameters to +use with textual data. + +Prior to libpng-1.5.4, the PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED +option was off by default, and slightly inaccurate scaling occurred. +This option can no longer be turned off, and the choice of accurate +or inaccurate 16-to-8 scaling is by using the new png_set_scale_16_to_8() +API for accurate scaling or the old png_set_strip_16_to_8() API for simple +chopping. + +Prior to libpng-1.5.4, the png_set_user_limits() function could only be +used to reduce the width and height limits from the value of +PNG_USER_WIDTH_MAX and PNG_USER_HEIGHT_MAX, although this document said +that it could be used to override them. Now this function will reduce or +increase the limits. + B. Changes to the build and configuration of libpng Details of internal changes to the library code can be found in the CHANGES @@ -5000,13 +5379,13 @@ Other rules can be inferred by inspecting the libpng source. .SH XIV. Y2K Compliance in libpng -February 3, 2011 +July 7, 2011 Since the PNG Development group is an ad-hoc body, we can't make an official declaration. This is your unofficial assurance that libpng from version 0.71 and -upward through 1.5.1 are Y2K compliant. It is my belief that earlier +upward through 1.5.4 are Y2K compliant. It is my belief that earlier versions were also Y2K compliant. Libpng only has three year fields. One is a 2-byte unsigned integer that @@ -5192,6 +5571,16 @@ the first widely used release: 1.5.1beta01-11 15 10501 15.so.15.1[.0] 1.5.1rc01-02 15 10501 15.so.15.1[.0] 1.5.1 15 10501 15.so.15.1[.0] + 1.5.2beta01-03 15 10502 15.so.15.2[.0] + 1.5.2rc01-03 15 10502 15.so.15.2[.0] + 1.5.2 15 10502 15.so.15.2[.0] + 1.5.3beta01-10 15 10503 15.so.15.3[.0] + 1.5.3rc01-02 15 10503 15.so.15.3[.0] + 1.5.3beta11 15 10503 15.so.15.3[.0] + 1.5.3 [omitted] + 1.5.4beta01-08 15 10504 15.so.15.4[.0] + 1.5.4rc01 15 10504 15.so.15.4[.0] + 1.5.4 15 10504 15.so.15.4[.0] Henceforth the source version will match the shared-library minor and patch numbers; the shared-library major version number will be @@ -5248,7 +5637,7 @@ possible without all of you. Thanks to Frank J. T. Wojcik for helping with the documentation. -Libpng version 1.5.1 - February 3, 2011: +Libpng version 1.5.4 - July 7, 2011: Initially created in 1995 by Guy Eric Schalnat, then of Group 42, Inc. Currently maintained by Glenn Randers-Pehrson (glennrp at users.sourceforge.net). @@ -5271,7 +5660,7 @@ this sentence. This code is released under the libpng license. -libpng versions 1.2.6, August 15, 2004, through 1.5.1, February 3, 2011, are +libpng versions 1.2.6, August 15, 2004, through 1.5.4, July 7, 2011, are Copyright (c) 2004,2006-2007 Glenn Randers-Pehrson, and are distributed according to the same disclaimer and license as libpng-1.2.5 with the following individual added to the list of Contributing Authors @@ -5370,7 +5759,7 @@ certification mark of the Open Source Initiative. Glenn Randers-Pehrson glennrp at users.sourceforge.net -February 3, 2011 +July 7, 2011 .\" end of man page diff --git a/src/3rdparty/libpng/libpngpf.3 b/src/3rdparty/libpng/libpngpf.3 index ff6e164..33c9ad3 100644 --- a/src/3rdparty/libpng/libpngpf.3 +++ b/src/3rdparty/libpng/libpngpf.3 @@ -1,6 +1,6 @@ -.TH LIBPNGPF 3 "February 3, 2011" +.TH LIBPNGPF 3 "July 7, 2011" .SH NAME -libpng \- Portable Network Graphics (PNG) Reference Library 1.5.1 +libpng \- Portable Network Graphics (PNG) Reference Library 1.5.4 (private functions) .SH SYNOPSIS \fB#include \fI"pngpriv.h" @@ -18,11 +18,9 @@ libpng \- Portable Network Graphics (PNG) Reference Library 1.5.1 \fI\fB .SH DESCRIPTION -The functions previously listed here are used privately by libpng +The functions previously listed here are used privately by libpng and are not recommended for use by applications. They are -not "exported" to applications using shared libraries. They -are listed alphabetically here as an aid to libpng maintainers. -See pngpriv.h for more information on these functions. +not "exported" to applications using shared libraries. .SH SEE ALSO .BR "png"(5), " libpng"(3), " zlib"(3), " deflate"(5), " " and " zlib"(5) diff --git a/src/3rdparty/libpng/png.5 b/src/3rdparty/libpng/png.5 index 9c5f8d3..0fca76e 100644 --- a/src/3rdparty/libpng/png.5 +++ b/src/3rdparty/libpng/png.5 @@ -1,4 +1,4 @@ -.TH PNG 5 "February 3, 2011" +.TH PNG 5 "July 7, 2011" .SH NAME png \- Portable Network Graphics (PNG) format .SH DESCRIPTION diff --git a/src/3rdparty/libpng/png.c b/src/3rdparty/libpng/png.c index 764f47c..eed3136 100644 --- a/src/3rdparty/libpng/png.c +++ b/src/3rdparty/libpng/png.c @@ -1,7 +1,7 @@ /* png.c - location for general purpose libpng functions * - * Last changed in libpng 1.5.1 [February 3, 2011] + * Last changed in libpng 1.5.4 [July 7, 2011] * Copyright (c) 1998-2011 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -14,7 +14,7 @@ #include "pngpriv.h" /* Generate a compiler error if there is an old png.h in the search path. */ -typedef png_libpng_version_1_5_1 Your_png_h_is_not_version_1_5_1; +typedef png_libpng_version_1_5_4 Your_png_h_is_not_version_1_5_4; /* Tells libpng that we have already handled the first "num_bytes" bytes * of the PNG file signature. If the PNG data is embedded into another @@ -137,6 +137,61 @@ png_calculate_crc(png_structp png_ptr, png_const_bytep ptr, png_size_t length) png_ptr->crc = crc32(png_ptr->crc, ptr, (uInt)length); } +/* Check a user supplied version number, called from both read and write + * functions that create a png_struct + */ +int +png_user_version_check(png_structp png_ptr, png_const_charp user_png_ver) +{ + if (user_png_ver) + { + int i = 0; + + do + { + if (user_png_ver[i] != png_libpng_ver[i]) + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + } while (png_libpng_ver[i++]); + } + + else + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + + if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) + { + /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so + * we must recompile any applications that use any older library version. + * For versions after libpng 1.0, we will be compatible, so we need + * only check the first digit. + */ + if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || + (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || + (user_png_ver[0] == '0' && user_png_ver[2] < '9')) + { +#ifdef PNG_WARNINGS_SUPPORTED + size_t pos = 0; + char m[128]; + + pos = png_safecat(m, sizeof m, pos, "Application built with libpng-"); + pos = png_safecat(m, sizeof m, pos, user_png_ver); + pos = png_safecat(m, sizeof m, pos, " but running with "); + pos = png_safecat(m, sizeof m, pos, png_libpng_ver); + + png_warning(png_ptr, m); +#endif + +#ifdef PNG_ERROR_NUMBERS_SUPPORTED + png_ptr->flags = 0; +#endif + + return 0; + } + } + + /* Success return. */ + return 1; +} + /* Allocate the memory for an info_struct for the application. We don't * really need the png_ptr, but it could potentially be useful in the * future. This should be used in favour of malloc(png_sizeof(png_info)) @@ -291,12 +346,10 @@ png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask, /* Free any sCAL entry */ if ((mask & PNG_FREE_SCAL) & info_ptr->free_me) { -#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED) png_free(png_ptr, info_ptr->scal_s_width); png_free(png_ptr, info_ptr->scal_s_height); info_ptr->scal_s_width = NULL; info_ptr->scal_s_height = NULL; -#endif info_ptr->valid &= ~PNG_INFO_sCAL; } #endif @@ -518,28 +571,37 @@ png_convert_to_rfc1123(png_structp png_ptr, png_const_timep ptime) if (png_ptr == NULL) return (NULL); - if (png_ptr->time_buffer == NULL) { - png_ptr->time_buffer = (png_charp)png_malloc(png_ptr, (png_uint_32)(29* - png_sizeof(char))); + size_t pos = 0; + char number_buf[5]; /* enough for a four digit year */ + +# define APPEND_STRING(string)\ + pos = png_safecat(png_ptr->time_buffer, sizeof png_ptr->time_buffer,\ + pos, (string)) +# define APPEND_NUMBER(format, value)\ + APPEND_STRING(PNG_FORMAT_NUMBER(number_buf, format, (value))) +# define APPEND(ch)\ + if (pos < (sizeof png_ptr->time_buffer)-1)\ + png_ptr->time_buffer[pos++] = (ch) + + APPEND_NUMBER(PNG_NUMBER_FORMAT_u, (unsigned)ptime->day % 32); + APPEND(' '); + APPEND_STRING(short_months[(ptime->month - 1) % 12]); + APPEND(' '); + APPEND_NUMBER(PNG_NUMBER_FORMAT_u, ptime->year); + APPEND(' '); + APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->hour % 24); + APPEND(':'); + APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->minute % 60); + APPEND(':'); + APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->second % 61); + APPEND_STRING(" +0000"); /* This reliably terminates the buffer */ + +# undef APPEND +# undef APPEND_NUMBER +# undef APPEND_STRING } -# ifdef USE_FAR_KEYWORD - { - char near_time_buf[29]; - png_snprintf6(near_time_buf, 29, "%d %s %d %02d:%02d:%02d +0000", - ptime->day % 32, short_months[(ptime->month - 1) % 12], - ptime->year, ptime->hour % 24, ptime->minute % 60, - ptime->second % 61); - png_memcpy(png_ptr->time_buffer, near_time_buf, - 29*png_sizeof(char)); - } -# else - png_snprintf6(png_ptr->time_buffer, 29, "%d %s %d %02d:%02d:%02d +0000", - ptime->day % 32, short_months[(ptime->month - 1) % 12], - ptime->year, ptime->hour % 24, ptime->minute % 60, - ptime->second % 61); -# endif return png_ptr->time_buffer; } # endif /* PNG_TIME_RFC1123_SUPPORTED */ @@ -555,13 +617,13 @@ png_get_copyright(png_const_structp png_ptr) #else # ifdef __STDC__ return PNG_STRING_NEWLINE \ - "libpng version 1.5.1 - February 3, 2011" PNG_STRING_NEWLINE \ + "libpng version 1.5.4 - July 7, 2011" PNG_STRING_NEWLINE \ "Copyright (c) 1998-2011 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \ "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \ PNG_STRING_NEWLINE; # else - return "libpng version 1.5.1 - February 3, 2011\ + return "libpng version 1.5.4 - July 7, 2011\ Copyright (c) 1998-2011 Glenn Randers-Pehrson\ Copyright (c) 1996-1997 Andreas Dilger\ Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc."; @@ -681,6 +743,13 @@ png_check_cHRM_fixed(png_structp png_ptr, if (png_ptr == NULL) return 0; + /* (x,y,z) values are first limited to 0..100000 (PNG_FP_1), the white + * y must also be greater than 0. To test for the upper limit calculate + * (PNG_FP_1-y) - x must be <= to this for z to be >= 0 (and the expression + * cannot overflow.) At this point we know x and y are >= 0 and (x+y) is + * <= PNG_FP_1. The previous test on PNG_MAX_UINT_31 is removed because it + * pointless (and it produces compiler warnings!) + */ if (white_x < 0 || white_y <= 0 || red_x < 0 || red_y < 0 || green_x < 0 || green_y < 0 || @@ -690,38 +759,26 @@ png_check_cHRM_fixed(png_structp png_ptr, "Ignoring attempt to set negative chromaticity value"); ret = 0; } - if (white_x > (png_fixed_point)PNG_UINT_31_MAX || - white_y > (png_fixed_point)PNG_UINT_31_MAX || - red_x > (png_fixed_point)PNG_UINT_31_MAX || - red_y > (png_fixed_point)PNG_UINT_31_MAX || - green_x > (png_fixed_point)PNG_UINT_31_MAX || - green_y > (png_fixed_point)PNG_UINT_31_MAX || - blue_x > (png_fixed_point)PNG_UINT_31_MAX || - blue_y > (png_fixed_point)PNG_UINT_31_MAX ) - { - png_warning(png_ptr, - "Ignoring attempt to set chromaticity value exceeding 21474.83"); - ret = 0; - } - if (white_x > 100000L - white_y) + /* And (x+y) must be <= PNG_FP_1 (so z is >= 0) */ + if (white_x > PNG_FP_1 - white_y) { png_warning(png_ptr, "Invalid cHRM white point"); ret = 0; } - if (red_x > 100000L - red_y) + if (red_x > PNG_FP_1 - red_y) { png_warning(png_ptr, "Invalid cHRM red point"); ret = 0; } - if (green_x > 100000L - green_y) + if (green_x > PNG_FP_1 - green_y) { png_warning(png_ptr, "Invalid cHRM green point"); ret = 0; } - if (blue_x > 100000L - blue_y) + if (blue_x > PNG_FP_1 - blue_y) { png_warning(png_ptr, "Invalid cHRM blue point"); ret = 0; @@ -763,7 +820,7 @@ png_check_IHDR(png_structp png_ptr, } # ifdef PNG_SET_USER_LIMITS_SUPPORTED - if (width > png_ptr->user_width_max || width > PNG_USER_WIDTH_MAX) + if (width > png_ptr->user_width_max) # else if (width > PNG_USER_WIDTH_MAX) @@ -774,7 +831,7 @@ png_check_IHDR(png_structp png_ptr, } # ifdef PNG_SET_USER_LIMITS_SUPPORTED - if (height > png_ptr->user_height_max || height > PNG_USER_HEIGHT_MAX) + if (height > png_ptr->user_height_max) # else if (height > PNG_USER_HEIGHT_MAX) # endif @@ -889,16 +946,9 @@ png_check_IHDR(png_structp png_ptr, /* Check an ASCII formated floating point value, see the more detailed * comments in pngpriv.h */ -/* The following is used internally to preserve the 'valid' flag */ +/* The following is used internally to preserve the sticky flags */ #define png_fp_add(state, flags) ((state) |= (flags)) -#define png_fp_set(state, value)\ - ((state) = (value) | ((state) & PNG_FP_WAS_VALID)) - -/* Internal type codes: bits above the base state! */ -#define PNG_FP_SIGN 0 /* [+-] */ -#define PNG_FP_DOT 4 /* . */ -#define PNG_FP_DIGIT 8 /* [0123456789] */ -#define PNG_FP_E 12 /* [Ee] */ +#define png_fp_set(state, value) ((state) = (value) | ((state) & PNG_FP_STICKY)) int /* PRIVATE */ png_check_fp_number(png_const_charp string, png_size_t size, int *statep, @@ -911,55 +961,55 @@ png_check_fp_number(png_const_charp string, png_size_t size, int *statep, { int type; /* First find the type of the next character */ + switch (string[i]) { - char ch = string[i]; - - if (ch >= 48 && ch <= 57) - type = PNG_FP_DIGIT; - - else switch (ch) - { - case 43: case 45: type = PNG_FP_SIGN; break; - case 46: type = PNG_FP_DOT; break; - case 69: case 101: type = PNG_FP_E; break; - default: goto PNG_FP_End; - } + case 43: type = PNG_FP_SAW_SIGN; break; + case 45: type = PNG_FP_SAW_SIGN + PNG_FP_NEGATIVE; break; + case 46: type = PNG_FP_SAW_DOT; break; + case 48: type = PNG_FP_SAW_DIGIT; break; + case 49: case 50: case 51: case 52: + case 53: case 54: case 55: case 56: + case 57: type = PNG_FP_SAW_DIGIT + PNG_FP_NONZERO; break; + case 69: + case 101: type = PNG_FP_SAW_E; break; + default: goto PNG_FP_End; } /* Now deal with this type according to the current * state, the type is arranged to not overlap the * bits of the PNG_FP_STATE. */ - switch ((state & PNG_FP_STATE) + type) + switch ((state & PNG_FP_STATE) + (type & PNG_FP_SAW_ANY)) { - case PNG_FP_INTEGER + PNG_FP_SIGN: + case PNG_FP_INTEGER + PNG_FP_SAW_SIGN: if (state & PNG_FP_SAW_ANY) goto PNG_FP_End; /* not a part of the number */ - png_fp_add(state, PNG_FP_SAW_SIGN); + png_fp_add(state, type); break; - case PNG_FP_INTEGER + PNG_FP_DOT: + case PNG_FP_INTEGER + PNG_FP_SAW_DOT: /* Ok as trailer, ok as lead of fraction. */ if (state & PNG_FP_SAW_DOT) /* two dots */ goto PNG_FP_End; else if (state & PNG_FP_SAW_DIGIT) /* trailing dot? */ - png_fp_add(state, PNG_FP_SAW_DOT); + png_fp_add(state, type); else - png_fp_set(state, PNG_FP_FRACTION | PNG_FP_SAW_DOT); + png_fp_set(state, PNG_FP_FRACTION | type); break; - case PNG_FP_INTEGER + PNG_FP_DIGIT: + case PNG_FP_INTEGER + PNG_FP_SAW_DIGIT: if (state & PNG_FP_SAW_DOT) /* delayed fraction */ png_fp_set(state, PNG_FP_FRACTION | PNG_FP_SAW_DOT); - png_fp_add(state, PNG_FP_SAW_DIGIT + PNG_FP_WAS_VALID); + png_fp_add(state, type | PNG_FP_WAS_VALID); break; - case PNG_FP_INTEGER + PNG_FP_E: + + case PNG_FP_INTEGER + PNG_FP_SAW_E: if ((state & PNG_FP_SAW_DIGIT) == 0) goto PNG_FP_End; @@ -967,17 +1017,17 @@ png_check_fp_number(png_const_charp string, png_size_t size, int *statep, break; - /* case PNG_FP_FRACTION + PNG_FP_SIGN: - goto PNG_FP_End; ** no sign in exponent */ + /* case PNG_FP_FRACTION + PNG_FP_SAW_SIGN: + goto PNG_FP_End; ** no sign in fraction */ - /* case PNG_FP_FRACTION + PNG_FP_DOT: + /* case PNG_FP_FRACTION + PNG_FP_SAW_DOT: goto PNG_FP_End; ** Because SAW_DOT is always set */ - case PNG_FP_FRACTION + PNG_FP_DIGIT: - png_fp_add(state, PNG_FP_SAW_DIGIT + PNG_FP_WAS_VALID); + case PNG_FP_FRACTION + PNG_FP_SAW_DIGIT: + png_fp_add(state, type | PNG_FP_WAS_VALID); break; - case PNG_FP_FRACTION + PNG_FP_E: + case PNG_FP_FRACTION + PNG_FP_SAW_E: /* This is correct because the trailing '.' on an * integer is handled above - so we can only get here * with the sequence ".E" (with no preceding digits). @@ -989,7 +1039,7 @@ png_check_fp_number(png_const_charp string, png_size_t size, int *statep, break; - case PNG_FP_EXPONENT + PNG_FP_SIGN: + case PNG_FP_EXPONENT + PNG_FP_SAW_SIGN: if (state & PNG_FP_SAW_ANY) goto PNG_FP_End; /* not a part of the number */ @@ -997,15 +1047,15 @@ png_check_fp_number(png_const_charp string, png_size_t size, int *statep, break; - /* case PNG_FP_EXPONENT + PNG_FP_DOT: + /* case PNG_FP_EXPONENT + PNG_FP_SAW_DOT: goto PNG_FP_End; */ - case PNG_FP_EXPONENT + PNG_FP_DIGIT: - png_fp_add(state, PNG_FP_SAW_DIGIT + PNG_FP_WAS_VALID); + case PNG_FP_EXPONENT + PNG_FP_SAW_DIGIT: + png_fp_add(state, PNG_FP_SAW_DIGIT | PNG_FP_WAS_VALID); break; - /* case PNG_FP_EXPONEXT + PNG_FP_E: + /* case PNG_FP_EXPONEXT + PNG_FP_SAW_E: goto PNG_FP_End; */ default: goto PNG_FP_End; /* I.e. break 2 */ @@ -1033,8 +1083,11 @@ png_check_fp_string(png_const_charp string, png_size_t size) int state=0; png_size_t char_index=0; - return png_check_fp_number(string, size, &state, &char_index) && - (char_index == size || string[char_index] == 0); + if (png_check_fp_number(string, size, &state, &char_index) && + (char_index == size || string[char_index] == 0)) + return state /* must be non-zero - see above */; + + return 0; /* i.e. fail */ } #endif /* pCAL or sCAL */ @@ -1102,7 +1155,7 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size, if (fp < 0) { fp = -fp; - *ascii++ = 45; /* '-' PLUS 1 TOTAL 1*/ + *ascii++ = 45; /* '-' PLUS 1 TOTAL 1 */ --size; } @@ -1329,7 +1382,7 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size, */ size -= cdigits; - *ascii++ = 69, --size; /* 'E': PLUS 1 TOTAL 2+precision*/ + *ascii++ = 69, --size; /* 'E': PLUS 1 TOTAL 2+precision */ if (exp_b10 < 0) { *ascii++ = 45, --size; /* '-': PLUS 1 TOTAL 3+precision */ @@ -1401,7 +1454,7 @@ png_ascii_from_fixed(png_structp png_ptr, png_charp ascii, png_size_t size, if (num <= 0x80000000U) /* else overflowed */ { - unsigned int ndigits = 0, first = 16/*flag value*/; + unsigned int ndigits = 0, first = 16 /* flag value */; char digits[10]; while (num) @@ -1495,7 +1548,7 @@ png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times, r /= divisor; r = floor(r+.5); - /* A png_fixed_point is a 32 bit integer. */ + /* A png_fixed_point is a 32-bit integer. */ if (r <= 2147483647. && r >= -2147483648.) { *res = (png_fixed_point)r; @@ -1540,7 +1593,7 @@ png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times, if (s32 < D) /* else overflow */ { - /* s32.s00 is now the 64 bit product, do a standard + /* s32.s00 is now the 64-bit product, do a standard * division, we know that s32 < D, so the maximum * required shift is 31. */ @@ -1683,7 +1736,7 @@ png_reciprocal2(png_fixed_point a, png_fixed_point b) * 2010: moved from pngset.c) */ /* * Multiply two 32-bit numbers, V1 and V2, using 32-bit - * arithmetic, to produce a 64 bit result in the HI/LO words. + * arithmetic, to produce a 64-bit result in the HI/LO words. * * A B * x C D @@ -1727,17 +1780,17 @@ png_64bit_product (long v1, long v2, unsigned long *hi_product, /* Fixed point gamma. * * To calculate gamma this code implements fast log() and exp() calls using only - * fixed point arithmetic. This code has sufficient precision for either 8 or - * 16 bit sample values. + * fixed point arithmetic. This code has sufficient precision for either 8-bit + * or 16-bit sample values. * * The tables used here were calculated using simple 'bc' programs, but C double * precision floating point arithmetic would work fine. The programs are given * at the head of each table. * - * 8 bit log table + * 8-bit log table * This is a table of -log(value/255)/log(2) for 'value' in the range 128 to - * 255, so it's the base 2 logarithm of a normalized 8 bit floating point - * mantissa. The numbers are 32 bit fractions. + * 255, so it's the base 2 logarithm of a normalized 8-bit floating point + * mantissa. The numbers are 32-bit fractions. */ static png_uint_32 png_8bit_l2[128] = @@ -1768,10 +1821,10 @@ png_8bit_l2[128] = 172473545U, 147538590U, 122703574U, 97967701U, 73330182U, 48790236U, 24347096U, 0U #if 0 - /* The following are the values for 16 bit tables - these work fine for the 8 - * bit conversions but produce very slightly larger errors in the 16 bit log - * (about 1.2 as opposed to 0.7 absolute error in the final value). To use - * these all the shifts below must be adjusted appropriately. + /* The following are the values for 16-bit tables - these work fine for the + * 8-bit conversions but produce very slightly larger errors in the 16-bit + * log (about 1.2 as opposed to 0.7 absolute error in the final value). To + * use these all the shifts below must be adjusted appropriately. */ 65166, 64430, 63700, 62976, 62257, 61543, 60835, 60132, 59434, 58741, 58054, 57371, 56693, 56020, 55352, 54689, 54030, 53375, 52726, 52080, 51439, 50803, @@ -1788,7 +1841,7 @@ png_8bit_l2[128] = #endif }; -static png_int_32 +PNG_STATIC png_int_32 png_log8bit(unsigned int x) { unsigned int lg2 = 0; @@ -1814,11 +1867,11 @@ png_log8bit(unsigned int x) return (png_int_32)((lg2 << 16) + ((png_8bit_l2[x-128]+32768)>>16)); } -/* The above gives exact (to 16 binary places) log2 values for 8 bit images, - * for 16 bit images we use the most significant 8 bits of the 16 bit value to +/* The above gives exact (to 16 binary places) log2 values for 8-bit images, + * for 16-bit images we use the most significant 8 bits of the 16-bit value to * get an approximation then multiply the approximation by a correction factor * determined by the remaining up to 8 bits. This requires an additional step - * in the 16 bit case. + * in the 16-bit case. * * We want log2(value/65535), we have log2(v'/255), where: * @@ -1827,8 +1880,8 @@ png_log8bit(unsigned int x) * * So f is value/v', which is equal to (256+v''/v') since v' is in the range 128 * to 255 and v'' is in the range 0 to 255 f will be in the range 256 to less - * than 258. The final factor also needs to correct for the fact that our 8 bit - * value is scaled by 255, whereas the 16 bit values must be scaled by 65535. + * than 258. The final factor also needs to correct for the fact that our 8-bit + * value is scaled by 255, whereas the 16-bit values must be scaled by 65535. * * This gives a final formula using a calculated value 'x' which is value/v' and * scaling by 65536 to match the above table: @@ -1838,13 +1891,13 @@ png_log8bit(unsigned int x) * Since these numbers are so close to '1' we can use simple linear * interpolation between the two end values 256/257 (result -368.61) and 258/257 * (result 367.179). The values used below are scaled by a further 64 to give - * 16 bit precision in the interpolation: + * 16-bit precision in the interpolation: * * Start (256): -23591 * Zero (257): 0 * End (258): 23499 */ -static png_int_32 +PNG_STATIC png_int_32 png_log16bit(png_uint_32 x) { unsigned int lg2 = 0; @@ -1865,7 +1918,7 @@ png_log16bit(png_uint_32 x) if ((x & 0x8000) == 0) lg2 += 1, x <<= 1; - /* Calculate the base logarithm from the top 8 bits as a 28 bit fractional + /* Calculate the base logarithm from the top 8 bits as a 28-bit fractional * value. */ lg2 <<= 28; @@ -1895,18 +1948,18 @@ png_log16bit(png_uint_32 x) return (png_int_32)((lg2 + 2048) >> 12); } -/* The 'exp()' case must invert the above, taking a 20 bit fixed point - * logarithmic value and returning a 16 or 8 bit number as appropriate. In +/* The 'exp()' case must invert the above, taking a 20-bit fixed point + * logarithmic value and returning a 16 or 8-bit number as appropriate. In * each case only the low 16 bits are relevant - the fraction - since the * integer bits (the top 4) simply determine a shift. * - * The worst case is the 16 bit distinction between 65535 and 65534, this + * The worst case is the 16-bit distinction between 65535 and 65534, this * requires perhaps spurious accuracty in the decoding of the logarithm to * distinguish log2(65535/65534.5) - 10^-5 or 17 bits. There is little chance * of getting this accuracy in practice. * * To deal with this the following exp() function works out the exponent of the - * frational part of the logarithm by using an accurate 32 bit value from the + * frational part of the logarithm by using an accurate 32-bit value from the * top four fractional bits then multiplying in the remaining bits. */ static png_uint_32 @@ -1915,7 +1968,7 @@ png_32bit_exp[16] = # if PNG_DO_BC for (i=0;i<16;++i) { .5 + e(-i/16*l(2))*2^32; } # endif - /* NOTE: the first entry is deliberately set to the maximum 32 bit value. */ + /* NOTE: the first entry is deliberately set to the maximum 32-bit value. */ 4294967295U, 4112874773U, 3938502376U, 3771522796U, 3611622603U, 3458501653U, 3311872529U, 3171459999U, 3037000500U, 2908241642U, 2784941738U, 2666869345U, 2553802834U, 2445529972U, 2341847524U, 2242560872U @@ -1938,12 +1991,12 @@ for (i=11;i>=0;--i){ print i, " ", (1 - e(-(2^i)/65536*l(2))) * 2^(32-i), "\n"} 0 45425.85339951654943850496 #endif -static png_uint_32 +PNG_STATIC png_uint_32 png_exp(png_fixed_point x) { if (x > 0 && x <= 0xfffff) /* Else overflow or zero (underflow) */ { - /* Obtain a 4 bit approximation */ + /* Obtain a 4-bit approximation */ png_uint_32 e = png_32bit_exp[(x >> 12) & 0xf]; /* Incorporate the low 12 bits - these decrease the returned value by @@ -1986,13 +2039,13 @@ png_exp(png_fixed_point x) return 0; } -static png_byte +PNG_STATIC png_byte png_exp8bit(png_fixed_point lg2) { - /* Get a 32 bit value: */ + /* Get a 32-bit value: */ png_uint_32 x = png_exp(lg2); - /* Convert the 32 bit value to 0..255 by multiplying by 256-1, note that the + /* Convert the 32-bit value to 0..255 by multiplying by 256-1, note that the * second, rounding, step can't overflow because of the first, subtraction, * step. */ @@ -2000,13 +2053,13 @@ png_exp8bit(png_fixed_point lg2) return (png_byte)((x + 0x7fffffU) >> 24); } -static png_uint_16 +PNG_STATIC png_uint_16 png_exp16bit(png_fixed_point lg2) { - /* Get a 32 bit value: */ + /* Get a 32-bit value: */ png_uint_32 x = png_exp(lg2); - /* Convert the 32 bit value to 0..65535 by multiplying by 65536-1: */ + /* Convert the 32-bit value to 0..65535 by multiplying by 65536-1: */ x -= x >> 16; return (png_uint_16)((x + 32767U) >> 16); } @@ -2059,9 +2112,9 @@ png_gamma_16bit_correct(unsigned int value, png_fixed_point gamma_val) } /* This does the right thing based on the bit_depth field of the - * png_struct, interpreting values as 8 or 16 bit. While the result - * is nominally a 16 bit value if bit depth is 8 then the result is - * 8 bit (as are the arguments.) + * png_struct, interpreting values as 8-bit or 16-bit. While the result + * is nominally a 16-bit value if bit depth is 8 then the result is + * 8-bit (as are the arguments.) */ png_uint_16 /* PRIVATE */ png_gamma_correct(png_structp png_ptr, unsigned int value, @@ -2084,7 +2137,7 @@ png_gamma_significant(png_fixed_point gamma_val) gamma_val > PNG_FP_1 + PNG_GAMMA_THRESHOLD_FIXED; } -/* Internal function to build a single 16 bit table - the table consists of +/* Internal function to build a single 16-bit table - the table consists of * 'num' 256 entry subtables, where 'num' is determined by 'shift' - the amount * to shift the input values right (or 16-number_of_signifiant_bits). * @@ -2111,7 +2164,7 @@ png_build_16bit_table(png_structp png_ptr, png_uint_16pp *ptable, (png_uint_16p)png_malloc(png_ptr, 256 * png_sizeof(png_uint_16)); /* The 'threshold' test is repeated here because it can arise for one of - * the 16 bit tables even if the others don't hit it. + * the 16-bit tables even if the others don't hit it. */ if (png_gamma_significant(gamma_val)) { @@ -2173,7 +2226,7 @@ png_build_16to8_table(png_structp png_ptr, png_uint_16pp *ptable, (png_uint_16pp)png_calloc(png_ptr, num * png_sizeof(png_uint_16p)); /* 'num' is the number of tables and also the number of low bits of low - * bits of the input 16 bit value used to select a table. Each table is + * bits of the input 16-bit value used to select a table. Each table is * itself index by the high 8 bits of the value. */ for (i = 0; i < num; i++) @@ -2183,24 +2236,24 @@ png_build_16to8_table(png_structp png_ptr, png_uint_16pp *ptable, /* 'gamma_val' is set to the reciprocal of the value calculated above, so * pow(out,g) is an *input* value. 'last' is the last input value set. * - * In the loop 'i' is used to find output values. Since the output is 8 - * bit there are only 256 possible values. The tables are set up to + * In the loop 'i' is used to find output values. Since the output is + * 8-bit there are only 256 possible values. The tables are set up to * select the closest possible output value for each input by finding * the input value at the boundary between each pair of output values * and filling the table up to that boundary with the lower output * value. * - * The boundary values are 0.5,1.5..253.5,254.5. Since these are 9 bit - * values the code below uses a 16 bit value in i; the values start at + * The boundary values are 0.5,1.5..253.5,254.5. Since these are 9-bit + * values the code below uses a 16-bit value in i; the values start at * 128.5 (for 0.5) and step by 257, for a total of 254 values (the last * entries are filled with 255). Start i at 128 and fill all 'last' * table entries <= 'max' */ last = 0; - for (i = 0; i < 255; ++i) /* 8 bit output value */ + for (i = 0; i < 255; ++i) /* 8-bit output value */ { /* Find the corresponding maximum input value */ - png_uint_16 out = (png_uint_16)(i * 257U); /* 16 bit output value */ + png_uint_16 out = (png_uint_16)(i * 257U); /* 16-bit output value */ /* Find the boundary value in 16 bits: */ png_uint_32 bound = png_gamma_16bit_correct(out+128U, gamma_val); @@ -2223,7 +2276,7 @@ png_build_16to8_table(png_structp png_ptr, png_uint_16pp *ptable, } } -/* Build a single 8 bit table: same as the 16 bit case but much simpler (and +/* Build a single 8-bit table: same as the 16-bit case but much simpler (and * typically much faster). Note that libpng currently does no sBIT processing * (apparently contrary to the spec) so a 256 entry table is always generated. */ @@ -2258,8 +2311,9 @@ png_build_gamma_table(png_structp png_ptr, int bit_depth) png_ptr->screen_gamma) : PNG_FP_1); #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) - if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY)) + if (png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) { png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1, png_reciprocal(png_ptr->gamma)); @@ -2268,7 +2322,7 @@ png_build_gamma_table(png_structp png_ptr, int bit_depth) png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) : png_ptr->gamma/* Probably doing rgb_to_gray */); } -#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ +#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ } else { @@ -2287,7 +2341,7 @@ png_build_gamma_table(png_structp png_ptr, int bit_depth) else sig_bit = png_ptr->sig_bit.gray; - /* 16 bit gamma code uses this equation: + /* 16-bit gamma code uses this equation: * * ov = table[(iv & 0xff) >> gamma_shift][iv >> 8] * @@ -2302,7 +2356,7 @@ png_build_gamma_table(png_structp png_ptr, int bit_depth) * * So the table 'n' corresponds to all those 'iv' of: * - * <all high 8 bit values><n << gamma_shift>..<(n+1 << gamma_shift)-1> + * <all high 8-bit values><n << gamma_shift>..<(n+1 << gamma_shift)-1> * */ if (sig_bit > 0 && sig_bit < 16U) @@ -2311,7 +2365,7 @@ png_build_gamma_table(png_structp png_ptr, int bit_depth) else shift = 0; /* keep all 16 bits */ - if (png_ptr->transformations & PNG_16_TO_8) + if (png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) { /* PNG_MAX_GAMMA_8 is the number of bits to keep - effectively * the significant bits in the *input* when the output will @@ -2327,7 +2381,12 @@ png_build_gamma_table(png_structp png_ptr, int bit_depth) png_ptr->gamma_shift = shift; #ifdef PNG_16BIT_SUPPORTED - if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND)) + /* NOTE: prior to 1.5.4 this test used to include PNG_BACKGROUND (now + * PNG_COMPOSE). This effectively smashed the background calculation for + * 16-bit output because the 8-bit table assumes the result will be reduced + * to 8 bits. + */ + if (png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) #endif png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift, png_ptr->screen_gamma > 0 ? png_product2(png_ptr->gamma, @@ -2341,8 +2400,9 @@ png_build_gamma_table(png_structp png_ptr, int bit_depth) #endif #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) - if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY)) + if (png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) { png_build_16bit_table(png_ptr, &png_ptr->gamma_16_to_1, shift, png_reciprocal(png_ptr->gamma)); @@ -2355,7 +2415,7 @@ png_build_gamma_table(png_structp png_ptr, int bit_depth) png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) : png_ptr->gamma/* Probably doing rgb_to_gray */); } -#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ +#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ } } #endif /* READ_GAMMA */ diff --git a/src/3rdparty/libpng/png.h b/src/3rdparty/libpng/png.h index 100f56d..c655a51 100644 --- a/src/3rdparty/libpng/png.h +++ b/src/3rdparty/libpng/png.h @@ -1,7 +1,7 @@ /* png.h - header file for PNG reference library * - * libpng version 1.5.1 - February 3, 2011 + * libpng version 1.5.4 - July 7, 2011 * Copyright (c) 1998-2011 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -11,7 +11,7 @@ * Authors and maintainers: * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat * libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger - * libpng versions 0.97, January 1998, through 1.5.1 - February 3, 2011: Glenn + * libpng versions 0.97, January 1998, through 1.5.4 - July 7, 2011: Glenn * See also "Contributing Authors", below. * * Note about libpng version numbers: @@ -147,6 +147,16 @@ * 1.5.1beta01-11 15 10501 15.so.15.1[.0] * 1.5.1rc01-02 15 10501 15.so.15.1[.0] * 1.5.1 15 10501 15.so.15.1[.0] + * 1.5.2beta01-03 15 10502 15.so.15.2[.0] + * 1.5.2rc01-03 15 10502 15.so.15.2[.0] + * 1.5.2 15 10502 15.so.15.2[.0] + * 1.5.3beta01-10 15 10503 15.so.15.3[.0] + * 1.5.3rc01-02 15 10503 15.so.15.3[.0] + * 1.5.3beta11 15 10503 15.so.15.3[.0] + * 1.5.3 [omitted] + * 1.5.4beta01-08 15 10504 15.so.15.4[.0] + * 1.5.4rc01 15 10504 15.so.15.4[.0] + * 1.5.4 15 10504 15.so.15.4[.0] * * Henceforth the source version will match the shared-library major * and minor numbers; the shared-library major version number will be @@ -178,7 +188,7 @@ * * This code is released under the libpng license. * - * libpng versions 1.2.6, August 15, 2004, through 1.5.1, February 3, 2011, are + * libpng versions 1.2.6, August 15, 2004, through 1.5.4, July 7, 2011, are * Copyright (c) 2004, 2006-2011 Glenn Randers-Pehrson, and are * distributed according to the same disclaimer and license as libpng-1.2.5 * with the following individual added to the list of Contributing Authors: @@ -205,7 +215,7 @@ * * libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson, and are - * distributed according to the same disclaimer and license as libpng-0.96, + * distributed according to the same disclaimer and license as libpng-0.96, * with the following individuals added to the list of Contributing Authors: * * Tom Lane @@ -214,7 +224,7 @@ * * libpng versions 0.89, June 1996, through 0.96, May 1997, are * Copyright (c) 1996, 1997 Andreas Dilger - * Distributed according to the same disclaimer and license as libpng-0.88, + * Distributed according to the same disclaimer and license as libpng-0.88, * with the following individuals added to the list of Contributing Authors: * * John Bowler @@ -237,10 +247,10 @@ * Tim Wegner * * The PNG Reference Library is supplied "AS IS". The Contributing Authors - * and Group 42, Inc. disclaim all warranties, expressed or implied, + * and Group 42, Inc. disclaim all warranties, expressed or implied, * including, without limitation, the warranties of merchantability and of * fitness for any purpose. The Contributing Authors and Group 42, Inc. - * assume no liability for direct, indirect, incidental, special, exemplary, + * assume no liability for direct, indirect, incidental, special, exemplary, * or consequential damages, which may result from the use of the PNG * Reference Library, even if advised of the possibility of such damage. * @@ -290,25 +300,24 @@ * Y2K compliance in libpng: * ========================= * - * February 3, 2011 + * July 7, 2011 * * Since the PNG Development group is an ad-hoc body, we can't make * an official declaration. * * This is your unofficial assurance that libpng from version 0.71 and - * upward through 1.5.1 are Y2K compliant. It is my belief that + * upward through 1.5.4 are Y2K compliant. It is my belief that * earlier versions were also Y2K compliant. * - * Libpng only has three year fields. One is a 2-byte unsigned integer - * that will hold years up to 65535. The other two hold the date in text + * Libpng only has two year fields. One is a 2-byte unsigned integer + * that will hold years up to 65535. The other holds the date in text * format, and will hold years up to 9999. * * The integer is * "png_uint_16 year" in png_time_struct. * - * The strings are - * "png_charp time_buffer" in png_struct and - * "near_time_buffer", which is a local character string in png.c. + * The string is + * "png_char time_buffer" in png_struct * * There are seven time-related functions: * png.c: png_convert_to_rfc_1123() in png.c @@ -326,7 +335,7 @@ * the full 4-digit year. There is a possibility that applications using * libpng are not passing 4-digit years into the png_convert_to_rfc_1123() * function, or that they are incorrectly passing only a 2-digit year - * instead of "year - 1900" into the png_convert_from_struct_tm() function, + * instead of "year - 1900" into the png_convert_from_struct_tm() function, * but this is not under our control. The libpng documentation has always * stated that it works with 4-digit years, and the APIs have been * documented as such. @@ -352,9 +361,9 @@ */ /* Version information for png.h - this should match the version in png.c */ -#define PNG_LIBPNG_VER_STRING "1.5.1" +#define PNG_LIBPNG_VER_STRING "1.5.4" #define PNG_HEADER_VERSION_STRING \ - " libpng version 1.5.1 - February 3, 2011\n" + " libpng version 1.5.4 - July 7, 2011\n" #define PNG_LIBPNG_VER_SONUM 15 #define PNG_LIBPNG_VER_DLLNUM 15 @@ -362,7 +371,7 @@ /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */ #define PNG_LIBPNG_VER_MAJOR 1 #define PNG_LIBPNG_VER_MINOR 5 -#define PNG_LIBPNG_VER_RELEASE 1 +#define PNG_LIBPNG_VER_RELEASE 4 /* This should match the numeric part of the final component of * PNG_LIBPNG_VER_STRING, omitting any leading zero: */ @@ -392,7 +401,7 @@ * version 1.0.0 was mis-numbered 100 instead of 10000). From * version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release */ -#define PNG_LIBPNG_VER 10501 /* 1.5.1 */ +#define PNG_LIBPNG_VER 10504 /* 1.5.4 */ /* Library configuration: these options cannot be changed after * the library has been built. @@ -405,19 +414,24 @@ #endif #ifndef PNG_VERSION_INFO_ONLY -/* Standard header files (not needed for the version info) */ -# ifdef PNG_SETJMP_SUPPORTED -# include <setjmp.h> +# ifndef PNG_BUILDING_SYMBOL_TABLE + /* + * Standard header files (not needed for the version info or while + * building symbol table -- see scripts/pnglibconf.dfa) + */ +# ifdef PNG_SETJMP_SUPPORTED +# include <setjmp.h> +# endif + + /* Need the time information for converting tIME chunks, it + * defines struct tm: + */ +# ifdef PNG_CONVERT_tIME_SUPPORTED + /* "time.h" functions are not supported on all operating systems */ +# include <time.h> +# endif # endif -/* Need the time information for converting tIME chunks, it - * defines struct tm: - */ -#ifdef PNG_CONVERT_tIME_SUPPORTED - /* "time.h" functions are not supported on all operating systems */ -# include <time.h> -#endif - /* Machine specific configuration. */ # include "pngconf.h" #endif @@ -509,7 +523,7 @@ extern "C" { /* This triggers a compiler error in png.c, if png.c and png.h * do not agree upon the version number. */ -typedef char* png_libpng_version_1_5_1; +typedef char* png_libpng_version_1_5_4; /* Three color definitions. The order of the red, green, and blue, (and the * exact size) is not important, although the size of the fields need to @@ -582,12 +596,12 @@ typedef PNG_CONST png_sPLT_t FAR * png_const_sPLT_tp; typedef png_sPLT_t FAR * FAR * png_sPLT_tpp; #ifdef PNG_TEXT_SUPPORTED -/* png_text holds the contents of a text/ztxt/itxt chunk in a PNG file, +/* png_text holds the contents of a text/ztxt/itxt chunk in a PNG file, * and whether that contents is compressed or not. The "key" field * points to a regular zero-terminated C string. The "text", "lang", and * "lang_key" fields can be regular C strings, empty strings, or NULL pointers. - * However, the * structure returned by png_get_text() will always contain - * regular zero-terminated C strings (possibly empty), never NULL pointers, + * However, the structure returned by png_get_text() will always contain + * regular zero-terminated C strings (possibly empty), never NULL pointers, * so they can be safely used in printf() and other string-handling functions. */ typedef struct png_text_struct @@ -657,12 +671,24 @@ typedef struct png_unknown_chunk_t /* libpng-using applications should NOT directly modify this byte. */ png_byte location; /* mode of operation at read time */ } + + png_unknown_chunk; typedef png_unknown_chunk FAR * png_unknown_chunkp; typedef PNG_CONST png_unknown_chunk FAR * png_const_unknown_chunkp; typedef png_unknown_chunk FAR * FAR * png_unknown_chunkpp; #endif +/* Values for the unknown chunk location byte */ + +#define PNG_HAVE_IHDR 0x01 +#define PNG_HAVE_PLTE 0x02 +#define PNG_AFTER_IDAT 0x08 + +/* The complete definition of png_info has, as of libpng-1.5.0, + * been moved into a separate header file that is not accessible to + * applications. Read libpng-manual.txt or libpng.3 for more info. + */ typedef struct png_info_def png_info; typedef png_info FAR * png_infop; typedef PNG_CONST png_info FAR * png_const_infop; @@ -678,6 +704,8 @@ typedef png_info FAR * FAR * png_infopp; */ #define PNG_FP_1 100000 #define PNG_FP_HALF 50000 +#define PNG_FP_MAX ((png_fixed_point)0x7fffffffL) +#define PNG_FP_MIN (-PNG_FP_MAX) /* These describe the color_type field in png_info. */ /* color type masks */ @@ -784,6 +812,14 @@ typedef struct png_row_info_struct typedef png_row_info FAR * png_row_infop; typedef png_row_info FAR * FAR * png_row_infopp; +/* The complete definition of png_struct has, as of libpng-1.5.0, + * been moved into a separate header file that is not accessible to + * applications. Read libpng-manual.txt or libpng.3 for more info. + */ +typedef struct png_struct_def png_struct; +typedef PNG_CONST png_struct FAR * png_const_structp; +typedef png_struct FAR * png_structp; + /* These are the function types for the I/O functions and for the functions * that allow the user to override the default I/O functions with his or her * own. The png_error_ptr type should match that of user-supplied warning @@ -792,61 +828,59 @@ typedef png_row_info FAR * FAR * png_row_infopp; * modify the buffer it is passed. The 'read' function, on the other hand, is * expected to return the read data in the buffer. */ -typedef struct png_struct_def png_struct; -typedef PNG_CONST png_struct FAR * png_const_structp; -typedef png_struct FAR * png_structp; - -typedef PNG_CALLBACK(void, *png_error_ptr, (png_structp, png_const_charp), ); -typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, png_size_t), ); -typedef PNG_CALLBACK(void, *png_flush_ptr, (png_structp), ); -typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32, - int), ); -typedef PNG_CALLBACK(void, *png_write_status_ptr, (png_structp, png_uint_32, - int), ); +typedef PNG_CALLBACK(void, *png_error_ptr, (png_structp, png_const_charp)); +typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, png_size_t)); +typedef PNG_CALLBACK(void, *png_flush_ptr, (png_structp)); +typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32, + int)); +typedef PNG_CALLBACK(void, *png_write_status_ptr, (png_structp, png_uint_32, + int)); #ifdef PNG_PROGRESSIVE_READ_SUPPORTED -typedef PNG_CALLBACK(void, *png_progressive_info_ptr, - (png_structp, png_infop), ); -typedef PNG_CALLBACK(void, *png_progressive_end_ptr, - (png_structp, png_infop), ); -typedef PNG_CALLBACK(void, *png_progressive_row_ptr, - (png_structp, png_bytep, png_uint_32, int), ); +typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop)); +typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop)); + +/* The following callback receives png_uint_32 row_number, int pass for the + * png_bytep data of the row. When transforming an interlaced image the + * row number is the row number within the sub-image of the interlace pass, so + * the value will increase to the height of the sub-image (not the full image) + * then reset to 0 for the next pass. + * + * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to + * find the output pixel (x,y) given an interlaced sub-image pixel + * (row,col,pass). (See below for these macros.) + */ +typedef PNG_CALLBACK(void, *png_progressive_row_ptr, (png_structp, png_bytep, + png_uint_32, int)); #endif #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) -typedef PNG_CALLBACK(void, *png_user_transform_ptr, - (png_structp, png_row_infop, png_bytep), ); +typedef PNG_CALLBACK(void, *png_user_transform_ptr, (png_structp, png_row_infop, + png_bytep)); #endif #ifdef PNG_USER_CHUNKS_SUPPORTED -typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp, - png_unknown_chunkp), ); +typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp, + png_unknown_chunkp)); #endif #ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED -typedef PNG_CALLBACK(void, *png_unknown_chunk_ptr, (png_structp), ); +typedef PNG_CALLBACK(void, *png_unknown_chunk_ptr, (png_structp)); #endif #ifdef PNG_SETJMP_SUPPORTED -/* This must match the function definition in <setjmp.h>, and the - * application must include this before png.h to obtain the definition - * of jmp_buf. The function is required to be PNG_NORETURN. (Note that - * PNG_PTR_NORETURN is used here because current versions of the Microsoft - * C compiler do not support the PNG_NORETURN attribute on a pointer.) - * - * If you get a type warning from the compiler when linking against this line - * then your compiler has 'longjmp' that does not match the requirements of the - * compiler that built libpng. You will have to write a wrapper function for - * your compiler's longjmp and call png_set_longjmp_fn directly (not via the - * png_jmpbuf macro.) - * - * If you get a warning here while building the library you will need to make +/* This must match the function definition in <setjmp.h>, and the application + * must include this before png.h to obtain the definition of jmp_buf. The + * function is required to be PNG_NORETURN, but this is not checked. If the + * function does return the application will crash via an abort() or similar + * system level call. + * + * If you get a warning here while building the library you may need to make * changes to ensure that pnglibconf.h records the calling convention used by * your compiler. This may be very difficult - try using a different compiler * to build the library! */ -typedef PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), - PNG_PTR_NORETURN); +PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef); #endif /* Transform masks for the high-level interface */ @@ -868,21 +902,24 @@ typedef PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), #define PNG_TRANSFORM_STRIP_FILLER_AFTER 0x1000 /* write only */ /* Added to libpng-1.4.0 */ #define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 /* read only */ +/* Added to libpng-1.5.4 */ +#define PNG_TRANSFORM_EXPAND_16 0x4000 /* read only */ +#define PNG_TRANSFORM_SCALE_16 0x8000 /* read only */ /* Flags for MNG supported features */ #define PNG_FLAG_MNG_EMPTY_PLTE 0x01 #define PNG_FLAG_MNG_FILTER_64 0x04 #define PNG_ALL_MNG_FEATURES 0x05 -/* NOTE: prior to 1.5 these functions had no 'API' style declaration, +/* NOTE: prior to 1.5 these functions had no 'API' style declaration, * this allowed the zlib default functions to be used on Windows * platforms. In 1.5 the zlib default malloc (which just calls malloc and * ignores the first argument) should be completely compatible with the * following. */ -typedef PNG_CALLBACK(png_voidp, *png_malloc_ptr, (png_structp, - png_alloc_size_t), ); -typedef PNG_CALLBACK(void, *png_free_ptr, (png_structp, png_voidp), ); +typedef PNG_CALLBACK(png_voidp, *png_malloc_ptr, (png_structp, + png_alloc_size_t)); +typedef PNG_CALLBACK(void, *png_free_ptr, (png_structp, png_voidp)); typedef png_struct FAR * FAR * png_structpp; @@ -928,7 +965,7 @@ PNG_EXPORT(2, void, png_set_sig_bytes, (png_structp png_ptr, int num_bytes)); * signature, and non-zero otherwise. Having num_to_check == 0 or * start > 7 will always fail (ie return non-zero). */ -PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, png_size_t start, +PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, png_size_t start, png_size_t num_to_check)); /* Simple signature checking function. This is the same as calling @@ -939,19 +976,19 @@ PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, png_size_t start, /* Allocate and initialize png_ptr struct for reading, and any other memory. */ PNG_EXPORTA(4, png_structp, png_create_read_struct, (png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn), + png_error_ptr error_fn, png_error_ptr warn_fn), PNG_ALLOCATED); /* Allocate and initialize png_ptr struct for writing, and any other memory */ PNG_EXPORTA(5, png_structp, png_create_write_struct, (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, - png_error_ptr warn_fn), + png_error_ptr warn_fn), PNG_ALLOCATED); PNG_EXPORT(6, png_size_t, png_get_compression_buffer_size, (png_const_structp png_ptr)); -PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structp png_ptr, +PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structp png_ptr, png_size_t size)); /* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp @@ -965,7 +1002,7 @@ PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structp png_ptr, * allocated by the library - the call will return NULL on a mismatch * indicating an ABI mismatch. */ -PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (png_structp png_ptr, +PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (png_structp png_ptr, png_longjmp_ptr longjmp_fn, size_t jmp_buf_size)); # define png_jmpbuf(png_ptr) \ (*png_set_longjmp_fn((png_ptr), longjmp, sizeof (jmp_buf))) @@ -990,13 +1027,13 @@ PNG_EXPORT(10, int, png_reset_zstream, (png_structp png_ptr)); #ifdef PNG_USER_MEM_SUPPORTED PNG_EXPORTA(11, png_structp, png_create_read_struct_2, (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, - png_error_ptr warn_fn, - png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), + png_error_ptr warn_fn, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), PNG_ALLOCATED); PNG_EXPORTA(12, png_structp, png_create_write_struct_2, (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, - png_error_ptr warn_fn, - png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), + png_error_ptr warn_fn, + png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), PNG_ALLOCATED); #endif @@ -1008,7 +1045,7 @@ PNG_EXPORT(14, void, png_write_chunk, (png_structp png_ptr, png_const_bytep chunk_name, png_const_bytep data, png_size_t length)); /* Write the start of a PNG chunk - length and chunk name. */ -PNG_EXPORT(15, void, png_write_chunk_start, (png_structp png_ptr, +PNG_EXPORT(15, void, png_write_chunk_start, (png_structp png_ptr, png_const_bytep chunk_name, png_uint_32 length)); /* Write the data of a PNG chunk started with png_write_chunk_start(). */ @@ -1019,10 +1056,10 @@ PNG_EXPORT(16, void, png_write_chunk_data, (png_structp png_ptr, PNG_EXPORT(17, void, png_write_chunk_end, (png_structp png_ptr)); /* Allocate and initialize the info structure */ -PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_structp png_ptr), +PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_structp png_ptr), PNG_ALLOCATED); -PNG_EXPORT(19, void, png_info_init_3, (png_infopp info_ptr, +PNG_EXPORT(19, void, png_info_init_3, (png_infopp info_ptr, png_size_t png_info_struct_size)); /* Writes all the PNG information before the image. */ @@ -1039,13 +1076,13 @@ PNG_EXPORT(22, void, png_read_info, #ifdef PNG_TIME_RFC1123_SUPPORTED PNG_EXPORT(23, png_const_charp, png_convert_to_rfc1123, - (png_structp png_ptr, + (png_structp png_ptr, png_const_timep ptime)); #endif #ifdef PNG_CONVERT_tIME_SUPPORTED /* Convert from a struct tm to png_time */ -PNG_EXPORT(24, void, png_convert_from_struct_tm, (png_timep ptime, +PNG_EXPORT(24, void, png_convert_from_struct_tm, (png_timep ptime, PNG_CONST struct tm FAR * ttime)); /* Convert from time_t to png_time. Uses gmtime() */ @@ -1061,6 +1098,13 @@ PNG_EXPORT(28, void, png_set_palette_to_rgb, (png_structp png_ptr)); PNG_EXPORT(29, void, png_set_tRNS_to_alpha, (png_structp png_ptr)); #endif +#ifdef PNG_READ_EXPAND_16_SUPPORTED +/* Expand to 16-bit channels, forces conversion of palette to RGB and expansion + * of a tRNS chunk if present. + */ +PNG_EXPORT(221, void, png_set_expand_16, (png_structp png_ptr)); +#endif + #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) /* Use blue, green, red order for pixels. */ PNG_EXPORT(30, void, png_set_bgr, (png_structp png_ptr)); @@ -1075,15 +1119,226 @@ PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structp png_ptr)); /* Reduce RGB to grayscale. */ PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structp png_ptr, int error_action, double red, double green)); -PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structp png_ptr, +PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structp png_ptr, int error_action, png_fixed_point red, png_fixed_point green)); PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structp png_ptr)); #endif -PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth, +#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth, png_colorp palette)); +#endif + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED +/* How the alpha channel is interpreted - this affects how the color channels of + * a PNG file are returned when an alpha channel, or tRNS chunk in a palette + * file, is present. + * + * This has no effect on the way pixels are written into a PNG output + * datastream. The color samples in a PNG datastream are never premultiplied + * with the alpha samples. + * + * The default is to return data according to the PNG specification: the alpha + * channel is a linear measure of the contribution of the pixel to the + * corresponding composited pixel. The gamma encoded color channels must be + * scaled according to the contribution and to do this it is necessary to undo + * the encoding, scale the color values, perform the composition and reencode + * the values. This is the 'PNG' mode. + * + * The alternative is to 'associate' the alpha with the color information by + * storing color channel values that have been scaled by the alpha. The + * advantage is that the color channels can be resampled (the image can be + * scaled) in this form. The disadvantage is that normal practice is to store + * linear, not (gamma) encoded, values and this requires 16-bit channels for + * still images rather than the 8-bit channels that are just about sufficient if + * gamma encoding is used. In addition all non-transparent pixel values, + * including completely opaque ones, must be gamma encoded to produce the final + * image. This is the 'STANDARD', 'ASSOCIATED' or 'PREMULTIPLIED' mode (the + * latter being the two common names for associated alpha color channels.) + * + * Since it is not necessary to perform arithmetic on opaque color values so + * long as they are not to be resampled and are in the final color space it is + * possible to optimize the handling of alpha by storing the opaque pixels in + * the PNG format (adjusted for the output color space) while storing partially + * opaque pixels in the standard, linear, format. The accuracy required for + * standard alpha composition is relatively low, because the pixels are + * isolated, therefore typically the accuracy loss in storing 8-bit linear + * values is acceptable. (This is not true if the alpha channel is used to + * simulate transparency over large areas - use 16 bits or the PNG mode in + * this case!) This is the 'OPTIMIZED' mode. For this mode a pixel is + * treated as opaque only if the alpha value is equal to the maximum value. + * + * The final choice is to gamma encode the alpha channel as well. This is + * broken because, in practice, no implementation that uses this choice + * correctly undoes the encoding before handling alpha composition. Use this + * choice only if other serious errors in the software or hardware you use + * mandate it; the typical serious error is for dark halos to appear around + * opaque areas of the composited PNG image because of arithmetic overflow. + * + * The API function png_set_alpha_mode specifies which of these choices to use + * with an enumerated 'mode' value and the gamma of the required output: + */ +#define PNG_ALPHA_PNG 0 /* according to the PNG standard */ +#define PNG_ALPHA_STANDARD 1 /* according to Porter/Duff */ +#define PNG_ALPHA_ASSOCIATED 1 /* as above; this is the normal practice */ +#define PNG_ALPHA_PREMULTIPLIED 1 /* as above */ +#define PNG_ALPHA_OPTIMIZED 2 /* 'PNG' for opaque pixels, else 'STANDARD' */ +#define PNG_ALPHA_BROKEN 3 /* the alpha channel is gamma encoded */ + +PNG_FP_EXPORT(227, void, png_set_alpha_mode, (png_structp png_ptr, int mode, + double output_gamma)); +PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structp png_ptr, + int mode, png_fixed_point output_gamma)); +#endif + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_ALPHA_MODE_SUPPORTED) +/* The output_gamma value is a screen gamma in libpng terminology: it expresses + * how to decode the output values, not how they are encoded. The values used + * correspond to the normal numbers used to describe the overall gamma of a + * computer display system; for example 2.2 for an sRGB conformant system. The + * values are scaled by 100000 in the _fixed version of the API (so 220000 for + * sRGB.) + * + * The inverse of the value is always used to provide a default for the PNG file + * encoding if it has no gAMA chunk and if png_set_gamma() has not been called + * to override the PNG gamma information. + * + * When the ALPHA_OPTIMIZED mode is selected the output gamma is used to encode + * opaque pixels however pixels with lower alpha values are not encoded, + * regardless of the output gamma setting. + * + * When the standard Porter Duff handling is requested with mode 1 the output + * encoding is set to be linear and the output_gamma value is only relevant + * as a default for input data that has no gamma information. The linear output + * encoding will be overridden if png_set_gamma() is called - the results may be + * highly unexpected! + * + * The following numbers are derived from the sRGB standard and the research + * behind it. sRGB is defined to be approximated by a PNG gAMA chunk value of + * 0.45455 (1/2.2) for PNG. The value implicitly includes any viewing + * correction required to take account of any differences in the color + * environment of the original scene and the intended display environment; the + * value expresses how to *decode* the image for display, not how the original + * data was *encoded*. + * + * sRGB provides a peg for the PNG standard by defining a viewing environment. + * sRGB itself, and earlier TV standards, actually use a more complex transform + * (a linear portion then a gamma 2.4 power law) than PNG can express. (PNG is + * limited to simple power laws.) By saying that an image for direct display on + * an sRGB conformant system should be stored with a gAMA chunk value of 45455 + * (11.3.3.2 and 11.3.3.5 of the ISO PNG specification) the PNG specification + * makes it possible to derive values for other display systems and + * environments. + * + * The Mac value is deduced from the sRGB based on an assumption that the actual + * extra viewing correction used in early Mac display systems was implemented as + * a power 1.45 lookup table. + * + * Any system where a programmable lookup table is used or where the behavior of + * the final display device characteristics can be changed requires system + * specific code to obtain the current characteristic. However this can be + * difficult and most PNG gamma correction only requires an approximate value. + * + * By default, if png_set_alpha_mode() is not called, libpng assumes that all + * values are unencoded, linear, values and that the output device also has a + * linear characteristic. This is only very rarely correct - it is invariably + * better to call png_set_alpha_mode() with PNG_DEFAULT_sRGB than rely on the + * default if you don't know what the right answer is! + * + * The special value PNG_GAMMA_MAC_18 indicates an older Mac system (pre Mac OS + * 10.6) which used a correction table to implement a somewhat lower gamma on an + * otherwise sRGB system. + * + * Both these values are reserved (not simple gamma values) in order to allow + * more precise correction internally in the future. + * + * NOTE: the following values can be passed to either the fixed or floating + * point APIs, but the floating point API will also accept floating point + * values. + */ +#define PNG_DEFAULT_sRGB -1 /* sRGB gamma and color space */ +#define PNG_GAMMA_MAC_18 -2 /* Old Mac '1.8' gamma and color space */ +#define PNG_GAMMA_sRGB 220000 /* Television standards--matches sRGB gamma */ +#define PNG_GAMMA_LINEAR PNG_FP_1 /* Linear */ +#endif + +/* The following are examples of calls to png_set_alpha_mode to achieve the + * required overall gamma correction and, where necessary, alpha + * premultiplication. + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); + * This is the default libpng handling of the alpha channel - it is not + * pre-multiplied into the color components. In addition the call states + * that the output is for a sRGB system and causes all PNG files without gAMA + * chunks to be assumed to be encoded using sRGB. + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); + * In this case the output is assumed to be something like an sRGB conformant + * display preceeded by a power-law lookup table of power 1.45. This is how + * early Mac systems behaved. + * + * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_GAMMA_LINEAR); + * This is the classic Jim Blinn approach and will work in academic + * environments where everything is done by the book. It has the shortcoming + * of assuming that input PNG data with no gamma information is linear - this + * is unlikely to be correct unless the PNG files where generated locally. + * Most of the time the output precision will be so low as to show + * significant banding in dark areas of the image. + * + * png_set_expand_16(pp); + * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_DEFAULT_sRGB); + * This is a somewhat more realistic Jim Blinn inspired approach. PNG files + * are assumed to have the sRGB encoding if not marked with a gamma value and + * the output is always 16 bits per component. This permits accurate scaling + * and processing of the data. If you know that your input PNG files were + * generated locally you might need to replace PNG_DEFAULT_sRGB with the + * correct value for your system. + * + * png_set_alpha_mode(pp, PNG_ALPHA_OPTIMIZED, PNG_DEFAULT_sRGB); + * If you just need to composite the PNG image onto an existing background + * and if you control the code that does this you can use the optimization + * setting. In this case you just copy completely opaque pixels to the + * output. For pixels that are not completely transparent (you just skip + * those) you do the composition math using png_composite or png_composite_16 + * below then encode the resultant 8-bit or 16-bit values to match the output + * encoding. + * + * Other cases + * If neither the PNG nor the standard linear encoding work for you because + * of the software or hardware you use then you have a big problem. The PNG + * case will probably result in halos around the image. The linear encoding + * will probably result in a washed out, too bright, image (it's actually too + * contrasty.) Try the ALPHA_OPTIMIZED mode above - this will probably + * substantially reduce the halos. Alternatively try: + * + * png_set_alpha_mode(pp, PNG_ALPHA_BROKEN, PNG_DEFAULT_sRGB); + * This option will also reduce the halos, but there will be slight dark + * halos round the opaque parts of the image where the background is light. + * In the OPTIMIZED mode the halos will be light halos where the background + * is dark. Take your pick - the halos are unavoidable unless you can get + * your hardware/software fixed! (The OPTIMIZED approach is slightly + * faster.) + * + * When the default gamma of PNG files doesn't match the output gamma. + * If you have PNG files with no gamma information png_set_alpha_mode allows + * you to provide a default gamma, but it also sets the ouput gamma to the + * matching value. If you know your PNG files have a gamma that doesn't + * match the output you can take advantage of the fact that + * png_set_alpha_mode always sets the output gamma but only sets the PNG + * default if it is not already set: + * + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB); + * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); + * The first call sets both the default and the output gamma values, the + * second call overrides the output gamma without changing the default. This + * is easier than achieving the same effect with png_set_gamma. You must use + * PNG_ALPHA_PNG for the first call - internal checking in png_set_alpha will + * fire if more than one call to png_set_alpha_mode and png_set_background is + * made in the same read operation, however multiple calls with PNG_ALPHA_PNG + * are ignored. + */ #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED PNG_EXPORT(36, void, png_set_strip_alpha, (png_structp png_ptr)); @@ -1101,14 +1356,14 @@ PNG_EXPORT(38, void, png_set_invert_alpha, (png_structp png_ptr)); #if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) /* Add a filler byte to 8-bit Gray or 24-bit RGB images. */ -PNG_EXPORT(39, void, png_set_filler, (png_structp png_ptr, png_uint_32 filler, +PNG_EXPORT(39, void, png_set_filler, (png_structp png_ptr, png_uint_32 filler, int flags)); /* The values of the PNG_FILLER_ defines should NOT be changed */ # define PNG_FILLER_BEFORE 0 # define PNG_FILLER_AFTER 1 /* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */ PNG_EXPORT(40, void, png_set_add_alpha, - (png_structp png_ptr, png_uint_32 filler, + (png_structp png_ptr, png_uint_32 filler, int flags)); #endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */ @@ -1151,12 +1406,16 @@ PNG_EXPORT(46, void, png_set_invert_mono, (png_structp png_ptr)); #endif #ifdef PNG_READ_BACKGROUND_SUPPORTED -/* Handle alpha and tRNS by replacing with a background color. */ -PNG_FP_EXPORT(47, void, png_set_background, (png_structp png_ptr, - png_const_color_16p background_color, int background_gamma_code, +/* Handle alpha and tRNS by replacing with a background color. Prior to + * libpng-1.5.4 this API must not be called before the PNG file header has been + * read. Doing so will result in unexpected behavior and possible warnings or + * errors if the PNG file contains a bKGD chunk. + */ +PNG_FP_EXPORT(47, void, png_set_background, (png_structp png_ptr, + png_const_color_16p background_color, int background_gamma_code, int need_expand, double background_gamma)); PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structp png_ptr, - png_const_color_16p background_color, int background_gamma_code, + png_const_color_16p background_color, int background_gamma_code, int need_expand, png_fixed_point background_gamma)); #endif #ifdef PNG_READ_BACKGROUND_SUPPORTED @@ -1166,7 +1425,13 @@ PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structp png_ptr, # define PNG_BACKGROUND_GAMMA_UNIQUE 3 #endif -#ifdef PNG_READ_16_TO_8_SUPPORTED +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED +/* Scale a 16-bit depth file down to 8-bit, accurately. */ +PNG_EXPORT(229, void, png_set_scale_16, (png_structp png_ptr)); +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED +#define PNG_READ_16_TO_8 SUPPORTED /* Name prior to 1.5.4 */ /* Strip the second byte of information from a 16-bit depth file. */ PNG_EXPORT(48, void, png_set_strip_16, (png_structp png_ptr)); #endif @@ -1176,8 +1441,8 @@ PNG_EXPORT(48, void, png_set_strip_16, (png_structp png_ptr)); * available. */ PNG_EXPORT(49, void, png_set_quantize, - (png_structp png_ptr, png_colorp palette, - int num_palette, int maximum_colors, png_const_uint_16p histogram, + (png_structp png_ptr, png_colorp palette, + int num_palette, int maximum_colors, png_const_uint_16p histogram, int full_quantize)); #endif @@ -1187,12 +1452,22 @@ PNG_EXPORT(49, void, png_set_quantize, */ #define PNG_GAMMA_THRESHOLD (PNG_GAMMA_THRESHOLD_FIXED*.00001) -/* Handle gamma correction. Screen_gamma=(display_exponent) */ +/* Handle gamma correction. Screen_gamma=(display_exponent). + * NOTE: this API simply sets the screen and file gamma values. It will + * therefore override the value for gamma in a PNG file if it is called after + * the file header has been read - use with care - call before reading the PNG + * file for best results! + * + * These routines accept the same gamma values as png_set_alpha_mode (described + * above). The PNG_GAMMA_ defines and PNG_DEFAULT_sRGB can be passed to either + * API (floating point or fixed.) Notice, however, that the 'file_gamma' value + * is the inverse of a 'screen gamma' value. + */ PNG_FP_EXPORT(50, void, png_set_gamma, - (png_structp png_ptr, double screen_gamma, - double default_file_gamma)); -PNG_FIXED_EXPORT(208, void, png_set_gamma_fixed, (png_structp png_ptr, - png_fixed_point screen_gamma, png_fixed_point default_file_gamma)); + (png_structp png_ptr, double screen_gamma, + double override_file_gamma)); +PNG_FIXED_EXPORT(208, void, png_set_gamma_fixed, (png_structp png_ptr, + png_fixed_point screen_gamma, png_fixed_point override_file_gamma)); #endif #ifdef PNG_WRITE_FLUSH_SUPPORTED @@ -1211,13 +1486,13 @@ PNG_EXPORT(54, void, png_read_update_info, #ifdef PNG_SEQUENTIAL_READ_SUPPORTED /* Read one or more rows of image data. */ -PNG_EXPORT(55, void, png_read_rows, (png_structp png_ptr, png_bytepp row, +PNG_EXPORT(55, void, png_read_rows, (png_structp png_ptr, png_bytepp row, png_bytepp display_row, png_uint_32 num_rows)); #endif #ifdef PNG_SEQUENTIAL_READ_SUPPORTED /* Read a row of data. */ -PNG_EXPORT(56, void, png_read_row, (png_structp png_ptr, png_bytep row, +PNG_EXPORT(56, void, png_read_row, (png_structp png_ptr, png_bytep row, png_bytep display_row)); #endif @@ -1235,7 +1510,7 @@ PNG_EXPORT(58, void, png_write_row, * of libpng and to allow the 'display_row' array from read_rows to be passed * unchanged to write_rows. */ -PNG_EXPORT(59, void, png_write_rows, (png_structp png_ptr, png_bytepp row, +PNG_EXPORT(59, void, png_write_rows, (png_structp png_ptr, png_bytepp row, png_uint_32 num_rows)); /* Write the image data */ @@ -1252,15 +1527,15 @@ PNG_EXPORT(62, void, png_read_end, (png_structp png_ptr, png_infop info_ptr)); #endif /* Free any memory associated with the png_info_struct */ -PNG_EXPORT(63, void, png_destroy_info_struct, (png_structp png_ptr, +PNG_EXPORT(63, void, png_destroy_info_struct, (png_structp png_ptr, png_infopp info_ptr_ptr)); /* Free any memory associated with the png_struct and the png_info_structs */ -PNG_EXPORT(64, void, png_destroy_read_struct, (png_structpp png_ptr_ptr, +PNG_EXPORT(64, void, png_destroy_read_struct, (png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); /* Free any memory associated with the png_struct and the png_info_structs */ -PNG_EXPORT(65, void, png_destroy_write_struct, (png_structpp png_ptr_ptr, +PNG_EXPORT(65, void, png_destroy_write_struct, (png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)); /* Set the libpng method of handling chunk CRC errors */ @@ -1270,7 +1545,7 @@ PNG_EXPORT(66, void, png_set_crc_action, /* Values for png_set_crc_action() say how to handle CRC errors in * ancillary and critical chunks, and whether to use the data contained * therein. Note that it is impossible to "discard" data in a critical - * chunk. For versions prior to 0.90, the action was always error/quit, + * chunk. For versions prior to 0.90, the action was always error/quit, * whereas in version 0.90 and later, the action for CRC errors in ancillary * chunks is warn/discard. These values should NOT be changed. * @@ -1350,11 +1625,11 @@ PNG_EXPORT(67, void, png_set_filter, * the weights and costs are set to 1.0, this degenerates the WEIGHTED method * to the UNWEIGHTED method, but with added encoding time/computation. */ -PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structp png_ptr, - int heuristic_method, int num_weights, png_const_doublep filter_weights, +PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structp png_ptr, + int heuristic_method, int num_weights, png_const_doublep filter_weights, png_const_doublep filter_costs)); PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed, - (png_structp png_ptr, + (png_structp png_ptr, int heuristic_method, int num_weights, png_const_fixed_point_p filter_weights, png_const_fixed_point_p filter_costs)); #endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ @@ -1367,30 +1642,56 @@ PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed, #define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ #define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ +#ifdef PNG_WRITE_SUPPORTED /* Set the library compression level. Currently, valid values range from * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 * (0 - no compression, 9 - "maximal" compression). Note that tests have * shown that zlib compression levels 3-6 usually perform as well as level 9 - * for PNG images, and do considerably fewer caclulations. In the future, + * for PNG images, and do considerably fewer caclulations. In the future, * these values may not correspond directly to the zlib compression levels. */ PNG_EXPORT(69, void, png_set_compression_level, (png_structp png_ptr, int level)); -PNG_EXPORT(70, void, png_set_compression_mem_level, (png_structp png_ptr, +PNG_EXPORT(70, void, png_set_compression_mem_level, (png_structp png_ptr, int mem_level)); -PNG_EXPORT(71, void, png_set_compression_strategy, (png_structp png_ptr, +PNG_EXPORT(71, void, png_set_compression_strategy, (png_structp png_ptr, int strategy)); -PNG_EXPORT(72, void, png_set_compression_window_bits, (png_structp png_ptr, +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +PNG_EXPORT(72, void, png_set_compression_window_bits, (png_structp png_ptr, int window_bits)); PNG_EXPORT(73, void, png_set_compression_method, (png_structp png_ptr, int method)); +#endif + +#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +/* Also set zlib parameters for compressing non-IDAT chunks */ +PNG_EXPORT(222, void, png_set_text_compression_level, + (png_structp png_ptr, int level)); + +PNG_EXPORT(223, void, png_set_text_compression_mem_level, (png_structp png_ptr, + int mem_level)); + +PNG_EXPORT(224, void, png_set_text_compression_strategy, (png_structp png_ptr, + int strategy)); + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +PNG_EXPORT(225, void, png_set_text_compression_window_bits, (png_structp + png_ptr, int window_bits)); + +PNG_EXPORT(226, void, png_set_text_compression_method, (png_structp png_ptr, + int method)); +#endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */ /* These next functions are called for input/output, memory, and error - * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, + * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, * and call standard C I/O routines such as fread(), fwrite(), and * fprintf(). These functions can be made to use other I/O routines * at run time for those applications that need to handle I/O in a @@ -1412,7 +1713,7 @@ PNG_EXPORT(74, void, png_init_io, (png_structp png_ptr, png_FILE_p fp)); */ PNG_EXPORT(75, void, png_set_error_fn, - (png_structp png_ptr, png_voidp error_ptr, + (png_structp png_ptr, png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn)); /* Return the user pointer associated with the error functions */ @@ -1428,43 +1729,43 @@ PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_structp png_ptr)); * default flush function, which uses the standard *FILE structure, will * be used. */ -PNG_EXPORT(77, void, png_set_write_fn, (png_structp png_ptr, png_voidp io_ptr, +PNG_EXPORT(77, void, png_set_write_fn, (png_structp png_ptr, png_voidp io_ptr, png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); /* Replace the default data input function with a user supplied one. */ -PNG_EXPORT(78, void, png_set_read_fn, (png_structp png_ptr, png_voidp io_ptr, +PNG_EXPORT(78, void, png_set_read_fn, (png_structp png_ptr, png_voidp io_ptr, png_rw_ptr read_data_fn)); /* Return the user pointer associated with the I/O functions */ PNG_EXPORT(79, png_voidp, png_get_io_ptr, (png_structp png_ptr)); -PNG_EXPORT(80, void, png_set_read_status_fn, (png_structp png_ptr, +PNG_EXPORT(80, void, png_set_read_status_fn, (png_structp png_ptr, png_read_status_ptr read_row_fn)); -PNG_EXPORT(81, void, png_set_write_status_fn, (png_structp png_ptr, +PNG_EXPORT(81, void, png_set_write_status_fn, (png_structp png_ptr, png_write_status_ptr write_row_fn)); #ifdef PNG_USER_MEM_SUPPORTED /* Replace the default memory allocation functions with user supplied one(s). */ -PNG_EXPORT(82, void, png_set_mem_fn, (png_structp png_ptr, png_voidp mem_ptr, +PNG_EXPORT(82, void, png_set_mem_fn, (png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn)); /* Return the user pointer associated with the memory functions */ PNG_EXPORT(83, png_voidp, png_get_mem_ptr, (png_const_structp png_ptr)); #endif #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED -PNG_EXPORT(84, void, png_set_read_user_transform_fn, (png_structp png_ptr, +PNG_EXPORT(84, void, png_set_read_user_transform_fn, (png_structp png_ptr, png_user_transform_ptr read_user_transform_fn)); #endif #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED -PNG_EXPORT(85, void, png_set_write_user_transform_fn, (png_structp png_ptr, +PNG_EXPORT(85, void, png_set_write_user_transform_fn, (png_structp png_ptr, png_user_transform_ptr write_user_transform_fn)); #endif #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED -PNG_EXPORT(86, void, png_set_user_transform_info, (png_structp png_ptr, - png_voidp user_transform_ptr, int user_transform_depth, +PNG_EXPORT(86, void, png_set_user_transform_info, (png_structp png_ptr, + png_voidp user_transform_ptr, int user_transform_depth, int user_transform_channels)); /* Return the user pointer associated with the user transform functions */ PNG_EXPORT(87, png_voidp, png_get_user_transform_ptr, @@ -1475,16 +1776,20 @@ PNG_EXPORT(87, png_voidp, png_get_user_transform_ptr, /* Return information about the row currently being processed. Note that these * APIs do not fail but will return unexpected results if called outside a user * transform callback. Also note that when transforming an interlaced image the - * row number is still the row in the final, de-interlaced, image but the row - * only contains the data of the current pass - consult png_row_info for the - * actual width of the row! + * row number is the row number within the sub-image of the interlace pass, so + * the value will increase to the height of the sub-image (not the full image) + * then reset to 0 for the next pass. + * + * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to + * find the output pixel (x,y) given an interlaced sub-image pixel + * (row,col,pass). (See below for these macros.) */ PNG_EXPORT(217, png_uint_32, png_get_current_row_number, (png_const_structp)); PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structp)); #endif #ifdef PNG_USER_CHUNKS_SUPPORTED -PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structp png_ptr, +PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structp png_ptr, png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); PNG_EXPORT(89, png_voidp, png_get_user_chunk_ptr, (png_const_structp png_ptr)); #endif @@ -1493,8 +1798,8 @@ PNG_EXPORT(89, png_voidp, png_get_user_chunk_ptr, (png_const_structp png_ptr)); /* Sets the function callbacks for the push reader, and a pointer to a * user-defined structure available to the callback functions. */ -PNG_EXPORT(90, void, png_set_progressive_read_fn, (png_structp png_ptr, - png_voidp progressive_ptr, png_progressive_info_ptr info_fn, +PNG_EXPORT(90, void, png_set_progressive_read_fn, (png_structp png_ptr, + png_voidp progressive_ptr, png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, png_progressive_end_ptr end_fn)); /* Returns the user pointer associated with the push read functions */ @@ -1502,7 +1807,7 @@ PNG_EXPORT(91, png_voidp, png_get_progressive_ptr, (png_const_structp png_ptr)); /* Function to be called when data becomes available */ PNG_EXPORT(92, void, png_process_data, - (png_structp png_ptr, png_infop info_ptr, + (png_structp png_ptr, png_infop info_ptr, png_bytep buffer, png_size_t buffer_size)); /* A function which may be called *only* within png_process_data to stop the @@ -1527,20 +1832,20 @@ PNG_EXPORT(220, png_uint_32, png_process_data_skip, (png_structp)); * stores its own version of the new data internally and ignores the passed * in value. */ -PNG_EXPORT(93, void, png_progressive_combine_row, (png_structp png_ptr, +PNG_EXPORT(93, void, png_progressive_combine_row, (png_structp png_ptr, png_bytep old_row, png_const_bytep new_row)); #endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ PNG_EXPORTA(94, png_voidp, png_malloc, - (png_structp png_ptr, png_alloc_size_t size), + (png_structp png_ptr, png_alloc_size_t size), PNG_ALLOCATED); /* Added at libpng version 1.4.0 */ PNG_EXPORTA(95, png_voidp, png_calloc, - (png_structp png_ptr, png_alloc_size_t size), + (png_structp png_ptr, png_alloc_size_t size), PNG_ALLOCATED); /* Added at libpng version 1.2.4 */ -PNG_EXPORTA(96, png_voidp, png_malloc_warn, (png_structp png_ptr, +PNG_EXPORTA(96, png_voidp, png_malloc_warn, (png_structp png_ptr, png_alloc_size_t size), PNG_ALLOCATED); /* Frees a pointer allocated by png_malloc() */ @@ -1575,7 +1880,7 @@ PNG_EXPORT(99, void, png_data_freer, #define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ #ifdef PNG_USER_MEM_SUPPORTED -PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_structp png_ptr, +PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_structp png_ptr, png_alloc_size_t size), PNG_ALLOCATED); PNG_EXPORT(101, void, png_free_default, (png_structp png_ptr, png_voidp ptr)); #endif @@ -1583,11 +1888,11 @@ PNG_EXPORT(101, void, png_free_default, (png_structp png_ptr, png_voidp ptr)); #ifdef PNG_ERROR_TEXT_SUPPORTED /* Fatal error in PNG image of libpng - can't continue */ PNG_EXPORTA(102, void, png_error, - (png_structp png_ptr, png_const_charp error_message), + (png_structp png_ptr, png_const_charp error_message), PNG_NORETURN); /* The same, but the chunk name is prepended to the error string. */ -PNG_EXPORTA(103, void, png_chunk_error, (png_structp png_ptr, +PNG_EXPORTA(103, void, png_chunk_error, (png_structp png_ptr, png_const_charp error_message), PNG_NORETURN); #else @@ -1595,24 +1900,26 @@ PNG_EXPORTA(103, void, png_chunk_error, (png_structp png_ptr, PNG_EXPORTA(104, void, png_err, (png_structp png_ptr), PNG_NORETURN); #endif +#ifdef PNG_WARNINGS_SUPPORTED /* Non-fatal error in libpng. Can continue, but may have a problem. */ -PNG_EXPORT(105, void, png_warning, (png_structp png_ptr, +PNG_EXPORT(105, void, png_warning, (png_structp png_ptr, png_const_charp warning_message)); /* Non-fatal error in libpng, chunk name is prepended to message. */ -PNG_EXPORT(106, void, png_chunk_warning, (png_structp png_ptr, +PNG_EXPORT(106, void, png_chunk_warning, (png_structp png_ptr, png_const_charp warning_message)); +#endif #ifdef PNG_BENIGN_ERRORS_SUPPORTED /* Benign error in libpng. Can continue, but may have a problem. * User can choose whether to handle as a fatal error or as a warning. */ # undef png_benign_error -PNG_EXPORT(107, void, png_benign_error, (png_structp png_ptr, +PNG_EXPORT(107, void, png_benign_error, (png_structp png_ptr, png_const_charp warning_message)); /* Same, chunk name is prepended to message. */ # undef png_chunk_benign_error -PNG_EXPORT(108, void, png_chunk_benign_error, (png_structp png_ptr, +PNG_EXPORT(108, void, png_chunk_benign_error, (png_structp png_ptr, png_const_charp warning_message)); PNG_EXPORT(109, void, png_set_benign_errors, @@ -1641,11 +1948,11 @@ PNG_EXPORT(109, void, png_set_benign_errors, */ /* Returns "flag" if chunk data is valid in info_ptr. */ PNG_EXPORT(110, png_uint_32, png_get_valid, - (png_const_structp png_ptr, png_const_infop info_ptr, + (png_const_structp png_ptr, png_const_infop info_ptr, png_uint_32 flag)); /* Returns number of bytes needed to hold a transformed row. */ -PNG_EXPORT(111, png_size_t, png_get_rowbytes, (png_const_structp png_ptr, +PNG_EXPORT(111, png_size_t, png_get_rowbytes, (png_const_structp png_ptr, png_const_infop info_ptr)); #ifdef PNG_INFO_IMAGE_SUPPORTED @@ -1667,11 +1974,11 @@ PNG_EXPORT(114, png_byte, png_get_channels, #ifdef PNG_EASY_ACCESS_SUPPORTED /* Returns image width in pixels. */ -PNG_EXPORT(115, png_uint_32, png_get_image_width, (png_const_structp png_ptr, +PNG_EXPORT(115, png_uint_32, png_get_image_width, (png_const_structp png_ptr, png_const_infop info_ptr)); /* Returns image height in pixels. */ -PNG_EXPORT(116, png_uint_32, png_get_image_height, (png_const_structp png_ptr, +PNG_EXPORT(116, png_uint_32, png_get_image_height, (png_const_structp png_ptr, png_const_infop info_ptr)); /* Returns image bit_depth. */ @@ -1679,19 +1986,19 @@ PNG_EXPORT(117, png_byte, png_get_bit_depth, (png_const_structp png_ptr, png_const_infop info_ptr)); /* Returns image color_type. */ -PNG_EXPORT(118, png_byte, png_get_color_type, (png_const_structp png_ptr, +PNG_EXPORT(118, png_byte, png_get_color_type, (png_const_structp png_ptr, png_const_infop info_ptr)); /* Returns image filter_type. */ -PNG_EXPORT(119, png_byte, png_get_filter_type, (png_const_structp png_ptr, +PNG_EXPORT(119, png_byte, png_get_filter_type, (png_const_structp png_ptr, png_const_infop info_ptr)); /* Returns image interlace_type. */ -PNG_EXPORT(120, png_byte, png_get_interlace_type, (png_const_structp png_ptr, +PNG_EXPORT(120, png_byte, png_get_interlace_type, (png_const_structp png_ptr, png_const_infop info_ptr)); /* Returns image compression_type. */ -PNG_EXPORT(121, png_byte, png_get_compression_type, (png_const_structp png_ptr, +PNG_EXPORT(121, png_byte, png_get_compression_type, (png_const_structp png_ptr, png_const_infop info_ptr)); /* Returns image resolution in pixels per meter, from pHYs chunk data. */ @@ -1705,7 +2012,7 @@ PNG_EXPORT(124, png_uint_32, png_get_y_pixels_per_meter, /* Returns pixel aspect ratio, computed from pHYs chunk data. */ PNG_FP_EXPORT(125, float, png_get_pixel_aspect_ratio, (png_const_structp png_ptr, png_const_infop info_ptr)); -PNG_FIXED_EXPORT(210, png_fixed_point, png_get_pixel_aspect_ratio_fixed, +PNG_FIXED_EXPORT(210, png_fixed_point, png_get_pixel_aspect_ratio_fixed, (png_const_structp png_ptr, png_const_infop info_ptr)); /* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ @@ -1726,47 +2033,47 @@ PNG_EXPORT(130, png_const_bytep, png_get_signature, #ifdef PNG_bKGD_SUPPORTED PNG_EXPORT(131, png_uint_32, png_get_bKGD, - (png_const_structp png_ptr, png_infop info_ptr, + (png_const_structp png_ptr, png_infop info_ptr, png_color_16p *background)); #endif #ifdef PNG_bKGD_SUPPORTED -PNG_EXPORT(132, void, png_set_bKGD, (png_structp png_ptr, png_infop info_ptr, +PNG_EXPORT(132, void, png_set_bKGD, (png_structp png_ptr, png_infop info_ptr, png_const_color_16p background)); #endif #ifdef PNG_cHRM_SUPPORTED -PNG_FP_EXPORT(133, png_uint_32, png_get_cHRM, (png_const_structp png_ptr, - png_const_infop info_ptr, double *white_x, double *white_y, double *red_x, - double *red_y, double *green_x, double *green_y, double *blue_x, +PNG_FP_EXPORT(133, png_uint_32, png_get_cHRM, (png_const_structp png_ptr, + png_const_infop info_ptr, double *white_x, double *white_y, double *red_x, + double *red_y, double *green_x, double *green_y, double *blue_x, double *blue_y)); #ifdef PNG_FIXED_POINT_SUPPORTED /* Otherwise not implemented */ PNG_FIXED_EXPORT(134, png_uint_32, png_get_cHRM_fixed, - (png_const_structp png_ptr, - png_const_infop info_ptr, png_fixed_point *int_white_x, - png_fixed_point *int_white_y, png_fixed_point *int_red_x, - png_fixed_point *int_red_y, png_fixed_point *int_green_x, - png_fixed_point *int_green_y, png_fixed_point *int_blue_x, + (png_const_structp png_ptr, + png_const_infop info_ptr, png_fixed_point *int_white_x, + png_fixed_point *int_white_y, png_fixed_point *int_red_x, + png_fixed_point *int_red_y, png_fixed_point *int_green_x, + png_fixed_point *int_green_y, png_fixed_point *int_blue_x, png_fixed_point *int_blue_y)); #endif #endif #ifdef PNG_cHRM_SUPPORTED PNG_FP_EXPORT(135, void, png_set_cHRM, - (png_structp png_ptr, png_infop info_ptr, - double white_x, double white_y, double red_x, double red_y, double green_x, + (png_structp png_ptr, png_infop info_ptr, + double white_x, double white_y, double red_x, double red_y, double green_x, double green_y, double blue_x, double blue_y)); -PNG_FIXED_EXPORT(136, void, png_set_cHRM_fixed, (png_structp png_ptr, - png_infop info_ptr, png_fixed_point int_white_x, - png_fixed_point int_white_y, png_fixed_point int_red_x, - png_fixed_point int_red_y, png_fixed_point int_green_x, - png_fixed_point int_green_y, png_fixed_point int_blue_x, +PNG_FIXED_EXPORT(136, void, png_set_cHRM_fixed, (png_structp png_ptr, + png_infop info_ptr, png_fixed_point int_white_x, + png_fixed_point int_white_y, png_fixed_point int_red_x, + png_fixed_point int_red_y, png_fixed_point int_green_x, + png_fixed_point int_green_y, png_fixed_point int_blue_x, png_fixed_point int_blue_y)); #endif #ifdef PNG_gAMA_SUPPORTED PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA, - (png_const_structp png_ptr, png_const_infop info_ptr, + (png_const_structp png_ptr, png_const_infop info_ptr, double *file_gamma)); PNG_FIXED_EXPORT(138, png_uint_32, png_get_gAMA_fixed, (png_const_structp png_ptr, png_const_infop info_ptr, @@ -1776,13 +2083,13 @@ PNG_FIXED_EXPORT(138, png_uint_32, png_get_gAMA_fixed, #ifdef PNG_gAMA_SUPPORTED PNG_FP_EXPORT(139, void, png_set_gAMA, (png_structp png_ptr, png_infop info_ptr, double file_gamma)); -PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_structp png_ptr, +PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_structp png_ptr, png_infop info_ptr, png_fixed_point int_file_gamma)); #endif #ifdef PNG_hIST_SUPPORTED PNG_EXPORT(141, png_uint_32, png_get_hIST, - (png_const_structp png_ptr, png_const_infop info_ptr, + (png_const_structp png_ptr, png_const_infop info_ptr, png_uint_16p *hist)); #endif @@ -1792,65 +2099,65 @@ PNG_EXPORT(142, void, png_set_hIST, (png_structp png_ptr, #endif PNG_EXPORT(143, png_uint_32, png_get_IHDR, - (png_structp png_ptr, png_infop info_ptr, - png_uint_32 *width, png_uint_32 *height, int *bit_depth, int *color_type, + (png_structp png_ptr, png_infop info_ptr, + png_uint_32 *width, png_uint_32 *height, int *bit_depth, int *color_type, int *interlace_method, int *compression_method, int *filter_method)); PNG_EXPORT(144, void, png_set_IHDR, - (png_structp png_ptr, png_infop info_ptr, - png_uint_32 width, png_uint_32 height, int bit_depth, int color_type, + (png_structp png_ptr, png_infop info_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, int color_type, int interlace_method, int compression_method, int filter_method)); #ifdef PNG_oFFs_SUPPORTED PNG_EXPORT(145, png_uint_32, png_get_oFFs, - (png_const_structp png_ptr, png_const_infop info_ptr, + (png_const_structp png_ptr, png_const_infop info_ptr, png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type)); #endif #ifdef PNG_oFFs_SUPPORTED PNG_EXPORT(146, void, png_set_oFFs, - (png_structp png_ptr, png_infop info_ptr, + (png_structp png_ptr, png_infop info_ptr, png_int_32 offset_x, png_int_32 offset_y, int unit_type)); #endif #ifdef PNG_pCAL_SUPPORTED PNG_EXPORT(147, png_uint_32, png_get_pCAL, - (png_const_structp png_ptr, png_const_infop info_ptr, + (png_const_structp png_ptr, png_const_infop info_ptr, png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type, - int *nparams, + int *nparams, png_charp *units, png_charpp *params)); #endif #ifdef PNG_pCAL_SUPPORTED PNG_EXPORT(148, void, png_set_pCAL, (png_structp png_ptr, - png_infop info_ptr, - png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type, + png_infop info_ptr, + png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams, png_const_charp units, png_charpp params)); #endif #ifdef PNG_pHYs_SUPPORTED PNG_EXPORT(149, png_uint_32, png_get_pHYs, - (png_const_structp png_ptr, png_const_infop info_ptr, + (png_const_structp png_ptr, png_const_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); #endif #ifdef PNG_pHYs_SUPPORTED PNG_EXPORT(150, void, png_set_pHYs, - (png_structp png_ptr, png_infop info_ptr, + (png_structp png_ptr, png_infop info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type)); #endif PNG_EXPORT(151, png_uint_32, png_get_PLTE, - (png_const_structp png_ptr, png_const_infop info_ptr, + (png_const_structp png_ptr, png_const_infop info_ptr, png_colorp *palette, int *num_palette)); PNG_EXPORT(152, void, png_set_PLTE, - (png_structp png_ptr, png_infop info_ptr, + (png_structp png_ptr, png_infop info_ptr, png_const_colorp palette, int num_palette)); #ifdef PNG_sBIT_SUPPORTED PNG_EXPORT(153, png_uint_32, png_get_sBIT, - (png_const_structp png_ptr, png_infop info_ptr, + (png_const_structp png_ptr, png_infop info_ptr, png_color_8p *sig_bit)); #endif @@ -1867,44 +2174,44 @@ PNG_EXPORT(155, png_uint_32, png_get_sRGB, (png_const_structp png_ptr, #ifdef PNG_sRGB_SUPPORTED PNG_EXPORT(156, void, png_set_sRGB, (png_structp png_ptr, png_infop info_ptr, int srgb_intent)); -PNG_EXPORT(157, void, png_set_sRGB_gAMA_and_cHRM, (png_structp png_ptr, +PNG_EXPORT(157, void, png_set_sRGB_gAMA_and_cHRM, (png_structp png_ptr, png_infop info_ptr, int srgb_intent)); #endif #ifdef PNG_iCCP_SUPPORTED PNG_EXPORT(158, png_uint_32, png_get_iCCP, - (png_const_structp png_ptr, png_const_infop info_ptr, - png_charpp name, int *compression_type, png_bytepp profile, + (png_const_structp png_ptr, png_const_infop info_ptr, + png_charpp name, int *compression_type, png_bytepp profile, png_uint_32 *proflen)); #endif #ifdef PNG_iCCP_SUPPORTED PNG_EXPORT(159, void, png_set_iCCP, - (png_structp png_ptr, png_infop info_ptr, - png_const_charp name, int compression_type, png_const_bytep profile, + (png_structp png_ptr, png_infop info_ptr, + png_const_charp name, int compression_type, png_const_bytep profile, png_uint_32 proflen)); #endif #ifdef PNG_sPLT_SUPPORTED PNG_EXPORT(160, png_uint_32, png_get_sPLT, - (png_const_structp png_ptr, png_const_infop info_ptr, + (png_const_structp png_ptr, png_const_infop info_ptr, png_sPLT_tpp entries)); #endif #ifdef PNG_sPLT_SUPPORTED PNG_EXPORT(161, void, png_set_sPLT, - (png_structp png_ptr, png_infop info_ptr, + (png_structp png_ptr, png_infop info_ptr, png_const_sPLT_tp entries, int nentries)); #endif #ifdef PNG_TEXT_SUPPORTED /* png_get_text also returns the number of text chunks in *num_text */ PNG_EXPORT(162, png_uint_32, png_get_text, - (png_const_structp png_ptr, png_const_infop info_ptr, + (png_const_structp png_ptr, png_const_infop info_ptr, png_textp *text_ptr, int *num_text)); #endif -/* Note while png_set_text() will accept a structure whose text, +/* Note while png_set_text() will accept a structure whose text, * language, and translated keywords are NULL pointers, the structure * returned by png_get_text will always contain regular * zero-terminated C strings. They might be empty strings but @@ -1913,7 +2220,7 @@ PNG_EXPORT(162, png_uint_32, png_get_text, #ifdef PNG_TEXT_SUPPORTED PNG_EXPORT(163, void, png_set_text, - (png_structp png_ptr, png_infop info_ptr, + (png_structp png_ptr, png_infop info_ptr, png_const_textp text_ptr, int num_text)); #endif @@ -1929,30 +2236,30 @@ PNG_EXPORT(165, void, png_set_tIME, #ifdef PNG_tRNS_SUPPORTED PNG_EXPORT(166, png_uint_32, png_get_tRNS, - (png_const_structp png_ptr, png_infop info_ptr, + (png_const_structp png_ptr, png_infop info_ptr, png_bytep *trans_alpha, int *num_trans, png_color_16p *trans_color)); #endif #ifdef PNG_tRNS_SUPPORTED PNG_EXPORT(167, void, png_set_tRNS, - (png_structp png_ptr, png_infop info_ptr, - png_const_bytep trans_alpha, int num_trans, + (png_structp png_ptr, png_infop info_ptr, + png_const_bytep trans_alpha, int num_trans, png_const_color_16p trans_color)); #endif #ifdef PNG_sCAL_SUPPORTED PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL, - (png_const_structp png_ptr, png_const_infop info_ptr, + (png_const_structp png_ptr, png_const_infop info_ptr, int *unit, double *width, double *height)); #ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED -/* NOTE: this API is currently implemented using floating point arithmetic, +/* NOTE: this API is currently implemented using floating point arithmetic, * consequently it can only be used on systems with floating point support. * In any case the range of values supported by png_fixed_point is small and it * is highly recommended that png_get_sCAL_s be used instead. */ PNG_FIXED_EXPORT(214, png_uint_32, png_get_sCAL_fixed, (png_structp png_ptr, png_const_infop info_ptr, int *unit, - png_fixed_point *width, + png_fixed_point *width, png_fixed_point *height)); #endif PNG_EXPORT(169, png_uint_32, png_get_sCAL_s, @@ -1960,13 +2267,13 @@ PNG_EXPORT(169, png_uint_32, png_get_sCAL_s, int *unit, png_charpp swidth, png_charpp sheight)); PNG_FP_EXPORT(170, void, png_set_sCAL, - (png_structp png_ptr, png_infop info_ptr, + (png_structp png_ptr, png_infop info_ptr, int unit, double width, double height)); -PNG_FIXED_EXPORT(213, void, png_set_sCAL_fixed, (png_structp png_ptr, - png_infop info_ptr, int unit, png_fixed_point width, +PNG_FIXED_EXPORT(213, void, png_set_sCAL_fixed, (png_structp png_ptr, + png_infop info_ptr, int unit, png_fixed_point width, png_fixed_point height)); PNG_EXPORT(171, void, png_set_sCAL_s, - (png_structp png_ptr, png_infop info_ptr, + (png_structp png_ptr, png_infop info_ptr, int unit, png_const_charp swidth, png_const_charp sheight)); #endif /* PNG_sCAL_SUPPORTED */ @@ -1981,23 +2288,23 @@ PNG_EXPORT(171, void, png_set_sCAL_s, = 3: keep even if unsafe-to-copy */ PNG_EXPORT(172, void, png_set_keep_unknown_chunks, - (png_structp png_ptr, int keep, + (png_structp png_ptr, int keep, png_const_bytep chunk_list, int num_chunks)); -PNG_EXPORT(173, int, png_handle_as_unknown, (png_structp png_ptr, +PNG_EXPORT(173, int, png_handle_as_unknown, (png_structp png_ptr, png_const_bytep chunk_name)); #endif #ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED -PNG_EXPORT(174, void, png_set_unknown_chunks, (png_structp png_ptr, +PNG_EXPORT(174, void, png_set_unknown_chunks, (png_structp png_ptr, png_infop info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns)); PNG_EXPORT(175, void, png_set_unknown_chunk_location, (png_structp png_ptr, png_infop info_ptr, int chunk, int location)); -PNG_EXPORT(176, int, png_get_unknown_chunks, (png_const_structp png_ptr, +PNG_EXPORT(176, int, png_get_unknown_chunks, (png_const_structp png_ptr, png_const_infop info_ptr, png_unknown_chunkpp entries)); #endif /* Png_free_data() will turn off the "valid" flag for anything it frees. - * If you need to turn it off for a chunk that your application has freed, + * If you need to turn it off for a chunk that your application has freed, * you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); */ PNG_EXPORT(177, void, png_set_invalid, @@ -2005,9 +2312,9 @@ PNG_EXPORT(177, void, png_set_invalid, #ifdef PNG_INFO_IMAGE_SUPPORTED /* The "params" pointer is currently not used and is for future expansion. */ -PNG_EXPORT(178, void, png_read_png, (png_structp png_ptr, png_infop info_ptr, +PNG_EXPORT(178, void, png_read_png, (png_structp png_ptr, png_infop info_ptr, int transforms, png_voidp params)); -PNG_EXPORT(179, void, png_write_png, (png_structp png_ptr, png_infop info_ptr, +PNG_EXPORT(179, void, png_write_png, (png_structp png_ptr, png_infop info_ptr, int transforms, png_voidp params)); #endif @@ -2021,7 +2328,7 @@ PNG_EXPORT(183, png_const_charp, png_get_libpng_ver, (png_const_structp png_ptr)); #ifdef PNG_MNG_FEATURES_SUPPORTED -PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (png_structp png_ptr, +PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (png_structp png_ptr, png_uint_32 mng_features_permitted)); #endif @@ -2036,25 +2343,25 @@ PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (png_structp png_ptr, */ #ifdef PNG_ERROR_NUMBERS_SUPPORTED PNG_EXPORT(185, void, png_set_strip_error_numbers, - (png_structp png_ptr, + (png_structp png_ptr, png_uint_32 strip_mode)); #endif /* Added in libpng-1.2.6 */ #ifdef PNG_SET_USER_LIMITS_SUPPORTED -PNG_EXPORT(186, void, png_set_user_limits, (png_structp png_ptr, +PNG_EXPORT(186, void, png_set_user_limits, (png_structp png_ptr, png_uint_32 user_width_max, png_uint_32 user_height_max)); PNG_EXPORT(187, png_uint_32, png_get_user_width_max, (png_const_structp png_ptr)); PNG_EXPORT(188, png_uint_32, png_get_user_height_max, (png_const_structp png_ptr)); /* Added in libpng-1.4.0 */ -PNG_EXPORT(189, void, png_set_chunk_cache_max, (png_structp png_ptr, +PNG_EXPORT(189, void, png_set_chunk_cache_max, (png_structp png_ptr, png_uint_32 user_chunk_cache_max)); PNG_EXPORT(190, png_uint_32, png_get_chunk_cache_max, (png_const_structp png_ptr)); /* Added in libpng-1.4.1 */ -PNG_EXPORT(191, void, png_set_chunk_malloc_max, (png_structp png_ptr, +PNG_EXPORT(191, void, png_set_chunk_malloc_max, (png_structp png_ptr, png_alloc_size_t user_chunk_cache_max)); PNG_EXPORT(192, png_alloc_size_t, png_get_chunk_malloc_max, (png_const_structp png_ptr)); @@ -2073,19 +2380,19 @@ PNG_EXPORT(195, png_uint_32, png_get_y_pixels_per_inch, PNG_FP_EXPORT(196, float, png_get_x_offset_inches, (png_const_structp png_ptr, png_const_infop info_ptr)); #ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ -PNG_FIXED_EXPORT(211, png_fixed_point, png_get_x_offset_inches_fixed, +PNG_FIXED_EXPORT(211, png_fixed_point, png_get_x_offset_inches_fixed, (png_structp png_ptr, png_const_infop info_ptr)); #endif -PNG_FP_EXPORT(197, float, png_get_y_offset_inches, (png_const_structp png_ptr, +PNG_FP_EXPORT(197, float, png_get_y_offset_inches, (png_const_structp png_ptr, png_const_infop info_ptr)); #ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ -PNG_FIXED_EXPORT(212, png_fixed_point, png_get_y_offset_inches_fixed, +PNG_FIXED_EXPORT(212, png_fixed_point, png_get_y_offset_inches_fixed, (png_structp png_ptr, png_const_infop info_ptr)); #endif # ifdef PNG_pHYs_SUPPORTED -PNG_EXPORT(198, png_uint_32, png_get_pHYs_dpi, (png_const_structp png_ptr, +PNG_EXPORT(198, png_uint_32, png_get_pHYs_dpi, (png_const_structp png_ptr, png_const_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); # endif /* PNG_pHYs_SUPPORTED */ @@ -2142,8 +2449,9 @@ PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type, #define PNG_PASS_COLS(width, pass) (((width)+(((1<<PNG_PASS_COL_SHIFT(pass))\ -1)-PNG_PASS_START_COL(pass)))>>PNG_PASS_COL_SHIFT(pass)) -/* For the progressive reader it is necessary to find the row in the output - * image given a row in an interlaced image, so two more macros: +/* For the reader row callbacks (both progressive and sequential) it is + * necessary to find the row in the output image given a row in an interlaced + * image, so two more macros: */ #define PNG_ROW_FROM_PASS_ROW(yIn, pass) \ (((yIn)<<PNG_PASS_ROW_SHIFT(pass))+PNG_PASS_START_ROW(pass)) @@ -2213,7 +2521,7 @@ PNG_EXPORT(202, png_uint_16, png_get_uint_16, (png_const_bytep buf)); PNG_EXPORT(203, png_int_32, png_get_int_32, (png_const_bytep buf)); #endif -PNG_EXPORT(204, png_uint_32, png_get_uint_31, (png_structp png_ptr, +PNG_EXPORT(204, png_uint_32, png_get_uint_31, (png_structp png_ptr, png_const_bytep buf)); /* No png_get_int_16 -- may be added if there's a real need for it. */ @@ -2226,7 +2534,7 @@ PNG_EXPORT(206, void, png_save_int_32, (png_bytep buf, png_int_32 i)); #endif /* Place a 16-bit number into a buffer in PNG byte order. - * The parameter is declared unsigned int, not png_uint_16, + * The parameter is declared unsigned int, not png_uint_16, * just to avoid potential problems on pre-ANSI C compilers. */ #ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED @@ -2268,7 +2576,7 @@ PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i)); * scripts/symbols.def as well. */ #ifdef PNG_EXPORT_LAST_ORDINAL - PNG_EXPORT_LAST_ORDINAL(220); + PNG_EXPORT_LAST_ORDINAL(229); #endif #ifdef __cplusplus diff --git a/src/3rdparty/libpng/pngconf.h b/src/3rdparty/libpng/pngconf.h index d0b3454..2a41a29 100644 --- a/src/3rdparty/libpng/pngconf.h +++ b/src/3rdparty/libpng/pngconf.h @@ -1,7 +1,7 @@ /* pngconf.h - machine configurable file for libpng * - * libpng version 1.5.1 - February 3, 2011 + * libpng version 1.5.4 - July 7, 2011 * * Copyright (c) 1998-2011 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) @@ -22,29 +22,31 @@ #ifndef PNGCONF_H #define PNGCONF_H +#ifndef PNG_BUILDING_SYMBOL_TABLE /* PNG_NO_LIMITS_H may be used to turn off the use of the standard C * definition file for machine specific limits, this may impact the * correctness of the definitons below (see uses of INT_MAX). */ -#ifndef PNG_NO_LIMITS_H -# include <limits.h> -#endif +# ifndef PNG_NO_LIMITS_H +# include <limits.h> +# endif /* For the memory copy APIs (i.e. the standard definitions of these), * because this file defines png_memcpy and so on the base APIs must * be defined here. */ -#if defined(BSD) && !defined(VXWORKS) -# include <strings.h> -#else -# include <string.h> -#endif +# if defined(BSD) && !defined(VXWORKS) +# include <strings.h> +# else +# include <string.h> +# endif /* For png_FILE_p - this provides the standard definition of a * FILE */ -#ifdef PNG_STDIO_SUPPORTED -# include <stdio.h> +# ifdef PNG_STDIO_SUPPORTED +# include <stdio.h> +# endif #endif /* This controls optimization of the reading of 16 and 32 bit values @@ -289,23 +291,15 @@ # endif #endif -/* THe following complexity is concerned with getting the 'attributes' of the - * declared function in the correct place. This potentially requires a separate - * PNG_EXPORT function for every compiler. +/* In 1.5.2 the definition of PNG_FUNCTION has been changed to always treat + * 'attributes' as a storage class - the attributes go at the start of the + * function definition, and attributes are always appended regardless of the + * compiler. This considerably simplifies these macros but may cause problems + * if any compilers both need function attributes and fail to handle them as + * a storage class (this is unlikely.) */ #ifndef PNG_FUNCTION -# ifdef __GNUC__ -# define PNG_FUNCTION(type, name, args, attributes)\ - attributes type name args -# else /* !GNUC */ -# ifdef _MSC_VER -# define PNG_FUNCTION(type, name, args, attributes)\ - attributes type name args -# else /* !MSC */ -# define PNG_FUNCTION(type, name, args, attributes)\ - type name args -# endif -# endif +# define PNG_FUNCTION(type, name, args, attributes) attributes type name args #endif #ifndef PNG_EXPORT_TYPE @@ -317,13 +311,19 @@ * scripts directory. */ #ifndef PNG_EXPORTA + # define PNG_EXPORTA(ordinal, type, name, args, attributes)\ - extern PNG_FUNCTION(PNG_EXPORT_TYPE(type),(PNGAPI name),PNGARG(args),\ - attributes) + PNG_FUNCTION(PNG_EXPORT_TYPE(type),(PNGAPI name),PNGARG(args), \ + extern attributes) #endif +/* ANSI-C (C90) does not permit a macro to be invoked with an empty argument, + * so make something non-empty to satisfy the requirement: + */ +#define PNG_EMPTY /*empty list*/ + #define PNG_EXPORT(ordinal, type, name, args)\ - PNG_EXPORTA(ordinal, type, name, args, ) + PNG_EXPORTA(ordinal, type, name, args, PNG_EMPTY) /* Use PNG_REMOVED to comment out a removed interface. */ #ifndef PNG_REMOVED @@ -331,8 +331,7 @@ #endif #ifndef PNG_CALLBACK -# define PNG_CALLBACK(type, name, args, attributes)\ - type (PNGCBAPI name) PNGARG(args) attributes +# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args) #endif /* Support for compiler specific function attributes. These are used @@ -354,16 +353,13 @@ * functions in png.h will generate compiler warnings. Added at libpng * version 1.2.41. */ -# ifdef __GNUC__ +# if defined(__GNUC__) # ifndef PNG_USE_RESULT # define PNG_USE_RESULT __attribute__((__warn_unused_result__)) # endif # ifndef PNG_NORETURN # define PNG_NORETURN __attribute__((__noreturn__)) # endif -# ifndef PNG_PTR_NORETURN -# define PNG_PTR_NORETURN __attribute__((__noreturn__)) -# endif # ifndef PNG_ALLOCATED # define PNG_ALLOCATED __attribute__((__malloc__)) # endif @@ -376,9 +372,6 @@ # ifndef PNG_DEPRECATED # define PNG_DEPRECATED __attribute__((__deprecated__)) # endif -# ifndef PNG_DEPSTRUCT -# define PNG_DEPSTRUCT __attribute__((__deprecated__)) -# endif # ifndef PNG_PRIVATE # if 0 /* Doesn't work so we use deprecated instead*/ # define PNG_PRIVATE \ @@ -387,21 +380,21 @@ # define PNG_PRIVATE \ __attribute__((__deprecated__)) # endif -# endif /* PNG_PRIVATE */ +# endif # endif /* PNGLIB_BUILD */ # endif /* __GNUC__ */ -# ifdef _MSC_VER /* may need to check value */ + +# if defined(_MSC_VER) && (_MSC_VER >= 1300) # ifndef PNG_USE_RESULT -# define PNG_USE_RESULT /*not supported*/ +# define PNG_USE_RESULT /* not supported */ # endif # ifndef PNG_NORETURN # define PNG_NORETURN __declspec(noreturn) # endif -# ifndef PNG_PTR_NORETURN -# define PNG_PTR_NORETURN /*not supported*/ -# endif # ifndef PNG_ALLOCATED -# define PNG_ALLOCATED __declspec(restrict) +# if (_MSC_VER >= 1400) +# define PNG_ALLOCATED __declspec(restrict) +# endif # endif /* This specifically protects structure members that should only be @@ -412,14 +405,11 @@ # ifndef PNG_DEPRECATED # define PNG_DEPRECATED __declspec(deprecated) # endif -# ifndef PNG_DEPSTRUCT -# define PNG_DEPSTRUCT __declspec(deprecated) -# endif # ifndef PNG_PRIVATE # define PNG_PRIVATE __declspec(deprecated) -# endif /* PNG_PRIVATE */ +# endif # endif /* PNGLIB_BUILD */ -# endif /* __GNUC__ */ +# endif /* _MSC_VER */ #endif /* PNG_PEDANTIC_WARNINGS */ #ifndef PNG_DEPRECATED @@ -434,9 +424,6 @@ #ifndef PNG_ALLOCATED # define PNG_ALLOCATED /* The result of the function is new memory */ #endif -#ifndef PNG_DEPSTRUCT -# define PNG_DEPSTRUCT /* Access to this struct member is deprecated */ -#endif #ifndef PNG_PRIVATE # define PNG_PRIVATE /* This is a private libpng function */ #endif diff --git a/src/3rdparty/libpng/pngerror.c b/src/3rdparty/libpng/pngerror.c index 8290bb4..4d4ceba 100644 --- a/src/3rdparty/libpng/pngerror.c +++ b/src/3rdparty/libpng/pngerror.c @@ -1,7 +1,7 @@ /* pngerror.c - stub functions for i/o and memory allocation * - * Last changed in libpng 1.5.1 [February 3, 2011] + * Last changed in libpng 1.5.4 [July 7, 2011] * Copyright (c) 1998-2011 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -89,15 +89,121 @@ png_error,(png_structp png_ptr, png_const_charp error_message),PNG_NORETURN) PNG_FUNCTION(void,PNGAPI png_err,(png_structp png_ptr),PNG_NORETURN) { + /* Prior to 1.5.2 the error_fn received a NULL pointer, expressed + * erroneously as '\0', instead of the empty string "". This was + * apparently an error, introduced in libpng-1.2.20, and png_default_error + * will crash in this case. + */ if (png_ptr != NULL && png_ptr->error_fn != NULL) - (*(png_ptr->error_fn))(png_ptr, '\0'); + (*(png_ptr->error_fn))(png_ptr, ""); /* If the custom handler doesn't exist, or if it returns, use the default handler, which will not return. */ - png_default_error(png_ptr, '\0'); + png_default_error(png_ptr, ""); } #endif /* PNG_ERROR_TEXT_SUPPORTED */ +/* Utility to safely appends strings to a buffer. This never errors out so + * error checking is not required in the caller. + */ +size_t +png_safecat(png_charp buffer, size_t bufsize, size_t pos, + png_const_charp string) +{ + if (buffer != NULL && pos < bufsize) + { + if (string != NULL) + while (*string != '\0' && pos < bufsize-1) + buffer[pos++] = *string++; + + buffer[pos] = '\0'; + } + + return pos; +} + +#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_TIME_RFC1123_SUPPORTED) +/* Utility to dump an unsigned value into a buffer, given a start pointer and + * and end pointer (which should point just *beyond* the end of the buffer!) + * Returns the pointer to the start of the formatted string. + */ +png_charp +png_format_number(png_const_charp start, png_charp end, int format, + png_alloc_size_t number) +{ + int count = 0; /* number of digits output */ + int mincount = 1; /* minimum number required */ + int output = 0; /* digit output (for the fixed point format) */ + + *--end = '\0'; + + /* This is written so that the loop always runs at least once, even with + * number zero. + */ + while (end > start && (number != 0 || count < mincount)) + { + + static const char digits[] = "0123456789ABCDEF"; + + switch (format) + { + case PNG_NUMBER_FORMAT_fixed: + /* Needs five digits (the fraction) */ + mincount = 5; + if (output || number % 10 != 0) + { + *--end = digits[number % 10]; + output = 1; + } + number /= 10; + break; + + case PNG_NUMBER_FORMAT_02u: + /* Expects at least 2 digits. */ + mincount = 2; + /* fall through */ + + case PNG_NUMBER_FORMAT_u: + *--end = digits[number % 10]; + number /= 10; + break; + + case PNG_NUMBER_FORMAT_02x: + /* This format expects at least two digits */ + mincount = 2; + /* fall through */ + + case PNG_NUMBER_FORMAT_x: + *--end = digits[number & 0xf]; + number >>= 4; + break; + + default: /* an error */ + number = 0; + break; + } + + /* Keep track of the number of digits added */ + ++count; + + /* Float a fixed number here: */ + if (format == PNG_NUMBER_FORMAT_fixed) if (count == 5) if (end > start) + { + /* End of the fraction, but maybe nothing was output? In that case + * drop the decimal point. If the number is a true zero handle that + * here. + */ + if (output) + *--end = '.'; + else if (number == 0) /* and !output */ + *--end = '0'; + } + } + + return end; +} +#endif + #ifdef PNG_WARNINGS_SUPPORTED /* This function is called whenever there is a non-fatal error. This function * should not be changed. If there is a need to handle warnings differently, @@ -128,6 +234,115 @@ png_warning(png_structp png_ptr, png_const_charp warning_message) else png_default_warning(png_ptr, warning_message + offset); } + +/* These functions support 'formatted' warning messages with up to + * PNG_WARNING_PARAMETER_COUNT parameters. In the format string the parameter + * is introduced by @<number>, where 'number' starts at 1. This follows the + * standard established by X/Open for internationalizable error messages. + */ +void +png_warning_parameter(png_warning_parameters p, int number, + png_const_charp string) +{ + if (number > 0 && number <= PNG_WARNING_PARAMETER_COUNT) + (void)png_safecat(p[number-1], (sizeof p[number-1]), 0, string); +} + +void +png_warning_parameter_unsigned(png_warning_parameters p, int number, int format, + png_alloc_size_t value) +{ + char buffer[PNG_NUMBER_BUFFER_SIZE]; + png_warning_parameter(p, number, PNG_FORMAT_NUMBER(buffer, format, value)); +} + +void +png_warning_parameter_signed(png_warning_parameters p, int number, int format, + png_int_32 value) +{ + png_alloc_size_t u; + png_charp str; + char buffer[PNG_NUMBER_BUFFER_SIZE]; + + /* Avoid overflow by doing the negate in a png_alloc_size_t: */ + u = (png_alloc_size_t)value; + if (value < 0) + u = ~u + 1; + + str = PNG_FORMAT_NUMBER(buffer, format, u); + + if (value < 0 && str > buffer) + *--str = '-'; + + png_warning_parameter(p, number, str); +} + +void +png_formatted_warning(png_structp png_ptr, png_warning_parameters p, + png_const_charp message) +{ + /* The internal buffer is just 128 bytes - enough for all our messages, + * overflow doesn't happen because this code checks! + */ + size_t i; + char msg[128]; + + for (i=0; i<(sizeof msg)-1 && *message != '\0'; ++i) + { + if (*message == '@') + { + int parameter = -1; + switch (*++message) + { + case '1': + parameter = 0; + break; + + case '2': + parameter = 1; + break; + + case '\0': + continue; /* To break out of the for loop above. */ + + default: + break; + } + + if (parameter >= 0 && parameter < PNG_WARNING_PARAMETER_COUNT) + { + /* Append this parameter */ + png_const_charp parm = p[parameter]; + png_const_charp pend = p[parameter] + (sizeof p[parameter]); + + /* No need to copy the trailing '\0' here, but there is no guarantee + * that parm[] has been initialized, so there is no guarantee of a + * trailing '\0': + */ + for (; i<(sizeof msg)-1 && parm != '\0' && parm < pend; ++i) + msg[i] = *parm++; + + ++message; + continue; + } + + /* else not a parameter and there is a character after the @ sign; just + * copy that. + */ + } + + /* At this point *message can't be '\0', even in the bad parameter case + * above where there is a lone '@' at the end of the message string. + */ + msg[i] = *message++; + } + + /* i is always less than (sizeof msg), so: */ + msg[i] = '\0'; + + /* And this is the formatted message: */ + png_warning(png_ptr, msg); +} #endif /* PNG_WARNINGS_SUPPORTED */ #ifdef PNG_BENIGN_ERRORS_SUPPORTED @@ -185,8 +400,13 @@ png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp { buffer[iout++] = ':'; buffer[iout++] = ' '; - png_memcpy(buffer + iout, error_message, PNG_MAX_ERROR_TEXT); - buffer[iout + PNG_MAX_ERROR_TEXT - 1] = '\0'; + + iin = 0; + while (iin < PNG_MAX_ERROR_TEXT-1 && error_message[iin] != '\0') + buffer[iout++] = error_message[iin++]; + + /* iin < PNG_MAX_ERROR_TEXT, so the following is safe: */ + buffer[iout] = '\0'; } } #endif /* PNG_WARNINGS_SUPPORTED || PNG_ERROR_TEXT_SUPPORTED */ @@ -272,7 +492,7 @@ png_set_longjmp_fn(png_structp png_ptr, png_longjmp_ptr longjmp_fn, return NULL; png_ptr->longjmp_fn = longjmp_fn; - return &png_ptr->png_jmpbuf; + return &png_ptr->longjmp_buffer; } #endif @@ -287,7 +507,8 @@ png_default_error,(png_structp png_ptr, png_const_charp error_message), { #ifdef PNG_CONSOLE_IO_SUPPORTED #ifdef PNG_ERROR_NUMBERS_SUPPORTED - if (*error_message == PNG_LITERAL_SHARP) + /* Check on NULL only added in 1.5.4 */ + if (error_message != NULL && *error_message == PNG_LITERAL_SHARP) { /* Strip "#nnnn " from beginning of error message. */ int offset; @@ -317,11 +538,11 @@ png_default_error,(png_structp png_ptr, png_const_charp error_message), else #endif { - fprintf(stderr, "libpng error: %s", error_message); + fprintf(stderr, "libpng error: %s", error_message ? error_message : + "undefined"); fprintf(stderr, PNG_STRING_NEWLINE); } -#endif -#ifndef PNG_CONSOLE_IO_SUPPORTED +#else PNG_UNUSED(error_message) /* Make compiler happy */ #endif png_longjmp(png_ptr, 1); @@ -335,13 +556,13 @@ png_longjmp,(png_structp png_ptr, int val),PNG_NORETURN) { # ifdef USE_FAR_KEYWORD { - jmp_buf png_jmpbuf; - png_memcpy(png_jmpbuf, png_ptr->png_jmpbuf, png_sizeof(jmp_buf)); - png_ptr->longjmp_fn(png_jmpbuf, val); + jmp_buf tmp_jmpbuf; + png_memcpy(tmp_jmpbuf, png_ptr->longjmp_buffer, png_sizeof(jmp_buf)); + png_ptr->longjmp_fn(tmp_jmpbuf, val); } # else - png_ptr->longjmp_fn(png_ptr->png_jmpbuf, val); + png_ptr->longjmp_fn(png_ptr->longjmp_buffer, val); # endif } #endif @@ -403,7 +624,7 @@ png_default_warning(png_structp png_ptr, png_const_charp warning_message) /* This function is called when the application wants to use another method * of handling errors and warnings. Note that the error function MUST NOT * return to the calling routine or serious problems will occur. The return - * method used in the default routine calls longjmp(png_ptr->png_jmpbuf, 1) + * method used in the default routine calls longjmp(png_ptr->longjmp_buffer, 1) */ void PNGAPI png_set_error_fn(png_structp png_ptr, png_voidp error_ptr, @@ -414,7 +635,11 @@ png_set_error_fn(png_structp png_ptr, png_voidp error_ptr, png_ptr->error_ptr = error_ptr; png_ptr->error_fn = error_fn; +#ifdef PNG_WARNINGS_SUPPORTED png_ptr->warning_fn = warning_fn; +#else + PNG_UNUSED(warning_fn) +#endif } diff --git a/src/3rdparty/libpng/pnginfo.h b/src/3rdparty/libpng/pnginfo.h index fa19f85..a33bfab 100644 --- a/src/3rdparty/libpng/pnginfo.h +++ b/src/3rdparty/libpng/pnginfo.h @@ -138,7 +138,6 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) * single color specified that should be treated as fully transparent. * Data is valid if (valid & PNG_INFO_tRNS) is non-zero. */ - png_bytep trans; /* alpha values for paletted image */ png_bytep trans_alpha; /* alpha values for paletted image */ png_color_16 trans_color; /* transparent color for non-palette image */ #endif diff --git a/src/3rdparty/libpng/pnglibconf.h b/src/3rdparty/libpng/pnglibconf.h index b1d2169..827d17e 100644 --- a/src/3rdparty/libpng/pnglibconf.h +++ b/src/3rdparty/libpng/pnglibconf.h @@ -3,7 +3,7 @@ /* pnglibconf.h - library build configuration */ -/* libpng version 1.5.0 - last changed on January 6, 2011 */ +/* libpng version 1.5.4 - last changed on June 22, 2011 */ /* Copyright (c) 1998-2011 Glenn Randers-Pehrson */ @@ -12,165 +12,176 @@ /* and license in png.h */ /* pnglibconf.h */ -/* Machine generated file: DO NOT EDIT */ /* Derived from: scripts/pnglibconf.dfa */ +/* If you edit this file by hand you must obey the rules expressed in */ +/* pnglibconf.dfa with respect to the dependencies between the following */ +/* symbols. It is much better to generate a new file using */ +/* scripts/libpngconf.mak */ + #ifndef PNGLCONF_H #define PNGLCONF_H /* settings */ -#define PNG_MAX_GAMMA_8 11 -#define PNG_CALLOC_SUPPORTED -#define PNG_QUANTIZE_RED_BITS 5 -#define PNG_USER_WIDTH_MAX 1000000L -#define PNG_QUANTIZE_GREEN_BITS 5 #define PNG_API_RULE 0 +#define PNG_CALLOC_SUPPORTED +#define PNG_COST_SHIFT 3 +#define PNG_DEFAULT_READ_MACROS 1 +#define PNG_GAMMA_THRESHOLD_FIXED 5000 +#define PNG_MAX_GAMMA_8 11 #define PNG_QUANTIZE_BLUE_BITS 5 +#define PNG_QUANTIZE_GREEN_BITS 5 +#define PNG_QUANTIZE_RED_BITS 5 +#define PNG_sCAL_PRECISION 5 #define PNG_USER_CHUNK_CACHE_MAX 0 +#define PNG_USER_CHUNK_MALLOC_MAX 0 #define PNG_USER_HEIGHT_MAX 1000000L -#define PNG_sCAL_PRECISION 5 -#define PNG_COST_SHIFT 3 +#define PNG_USER_WIDTH_MAX 1000000L #define PNG_WEIGHT_SHIFT 8 -#define PNG_USER_CHUNK_MALLOC_MAX 0 -#define PNG_DEFAULT_READ_MACROS 1 #define PNG_ZBUF_SIZE 8192 -#define PNG_GAMMA_THRESHOLD_FIXED 5000 /* end of settings */ /* options */ -#define PNG_INFO_IMAGE_SUPPORTED -#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED -#define PNG_POINTER_INDEXING_SUPPORTED -#define PNG_WARNINGS_SUPPORTED -#define PNG_FLOATING_ARITHMETIC_SUPPORTED -#define PNG_WRITE_SUPPORTED -#define PNG_WRITE_INTERLACING_SUPPORTED -#define PNG_WRITE_16BIT_SUPPORTED -#define PNG_EASY_ACCESS_SUPPORTED +#define PNG_16BIT_SUPPORTED #define PNG_ALIGN_MEMORY_SUPPORTED -#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED -#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED -#define PNG_USER_LIMITS_SUPPORTED -#define PNG_FIXED_POINT_SUPPORTED +#define PNG_BENIGN_ERRORS_SUPPORTED +#define PNG_bKGD_SUPPORTED +#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +#define PNG_CHECK_cHRM_SUPPORTED +#define PNG_cHRM_SUPPORTED +#define PNG_CONSOLE_IO_SUPPORTED +#define PNG_CONVERT_tIME_SUPPORTED +#define PNG_EASY_ACCESS_SUPPORTED /*#undef PNG_ERROR_NUMBERS_SUPPORTED*/ #define PNG_ERROR_TEXT_SUPPORTED -#define PNG_READ_SUPPORTED -/*#undef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED*/ -#define PNG_BENIGN_ERRORS_SUPPORTED -#define PNG_SETJMP_SUPPORTED -#define PNG_WRITE_FLUSH_SUPPORTED -#define PNG_MNG_FEATURES_SUPPORTED +#define PNG_FIXED_POINT_SUPPORTED +#define PNG_FLOATING_ARITHMETIC_SUPPORTED #define PNG_FLOATING_POINT_SUPPORTED +#define PNG_gAMA_SUPPORTED +#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +#define PNG_hIST_SUPPORTED +#define PNG_iCCP_SUPPORTED #define PNG_INCH_CONVERSIONS_SUPPORTED -#define PNG_STDIO_SUPPORTED -#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED -#define PNG_USER_MEM_SUPPORTED +#define PNG_INFO_IMAGE_SUPPORTED #define PNG_IO_STATE_SUPPORTED -#define PNG_SET_USER_LIMITS_SUPPORTED +#define PNG_iTXt_SUPPORTED +#define PNG_MNG_FEATURES_SUPPORTED +#define PNG_oFFs_SUPPORTED +#define PNG_pCAL_SUPPORTED +#define PNG_pHYs_SUPPORTED +#define PNG_POINTER_INDEXING_SUPPORTED +#define PNG_PROGRESSIVE_READ_SUPPORTED +#define PNG_READ_16BIT_SUPPORTED +#define PNG_READ_ALPHA_MODE_SUPPORTED #define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED -#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED -#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED -#define PNG_WRITE_FILTER_SUPPORTED -#define PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED -#define PNG_WRITE_iCCP_SUPPORTED -#define PNG_READ_TRANSFORMS_SUPPORTED -#define PNG_READ_GAMMA_SUPPORTED +#define PNG_READ_BACKGROUND_SUPPORTED +#define PNG_READ_BGR_SUPPORTED #define PNG_READ_bKGD_SUPPORTED -#define PNG_UNKNOWN_CHUNKS_SUPPORTED -#define PNG_READ_sCAL_SUPPORTED -#define PNG_WRITE_hIST_SUPPORTED -#define PNG_READ_OPT_PLTE_SUPPORTED -#define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED -#define PNG_WRITE_gAMA_SUPPORTED +#define PNG_READ_cHRM_SUPPORTED +#define PNG_READ_COMPOSITE_NODIV_SUPPORTED +#define PNG_READ_COMPRESSED_TEXT_SUPPORTED +#define PNG_READ_EXPAND_16_SUPPORTED +#define PNG_READ_EXPAND_SUPPORTED +#define PNG_READ_FILLER_SUPPORTED +#define PNG_READ_gAMA_SUPPORTED +#define PNG_READ_GAMMA_SUPPORTED #define PNG_READ_GRAY_TO_RGB_SUPPORTED -#define PNG_WRITE_pCAL_SUPPORTED +#define PNG_READ_hIST_SUPPORTED +#define PNG_READ_iCCP_SUPPORTED +#define PNG_READ_INTERLACING_SUPPORTED +#define PNG_READ_INT_FUNCTIONS_SUPPORTED #define PNG_READ_INVERT_ALPHA_SUPPORTED -#define PNG_WRITE_TRANSFORMS_SUPPORTED -#define PNG_READ_sBIT_SUPPORTED +#define PNG_READ_INVERT_SUPPORTED +#define PNG_READ_iTXt_SUPPORTED +#define PNG_READ_oFFs_SUPPORTED +#define PNG_READ_OPT_PLTE_SUPPORTED #define PNG_READ_PACK_SUPPORTED -#define PNG_WRITE_SWAP_SUPPORTED -#define PNG_READ_cHRM_SUPPORTED -#define PNG_WRITE_tIME_SUPPORTED -#define PNG_READ_INTERLACING_SUPPORTED -#define PNG_READ_tRNS_SUPPORTED -#define PNG_WRITE_pHYs_SUPPORTED -#define PNG_WRITE_INVERT_SUPPORTED +#define PNG_READ_PACKSWAP_SUPPORTED +#define PNG_READ_pCAL_SUPPORTED +#define PNG_READ_pHYs_SUPPORTED +#define PNG_READ_QUANTIZE_SUPPORTED #define PNG_READ_RGB_TO_GRAY_SUPPORTED -#define PNG_WRITE_sRGB_SUPPORTED -#define PNG_READ_oFFs_SUPPORTED -#define PNG_WRITE_FILLER_SUPPORTED -#define PNG_WRITE_TEXT_SUPPORTED -#define PNG_WRITE_SHIFT_SUPPORTED -#define PNG_PROGRESSIVE_READ_SUPPORTED +#define PNG_READ_sBIT_SUPPORTED +#define PNG_READ_SCALE_16_TO_8_SUPPORTED +#define PNG_READ_sCAL_SUPPORTED #define PNG_READ_SHIFT_SUPPORTED -#define PNG_CONVERT_tIME_SUPPORTED -#define PNG_READ_USER_TRANSFORM_SUPPORTED -#define PNG_READ_INT_FUNCTIONS_SUPPORTED -#define PNG_READ_USER_CHUNKS_SUPPORTED -#define PNG_READ_hIST_SUPPORTED -#define PNG_READ_16BIT_SUPPORTED -#define PNG_READ_SWAP_ALPHA_SUPPORTED -#define PNG_READ_COMPOSITE_NODIV_SUPPORTED -#define PNG_SEQUENTIAL_READ_SUPPORTED -#define PNG_READ_BACKGROUND_SUPPORTED -#define PNG_READ_QUANTIZE_SUPPORTED -#define PNG_READ_iCCP_SUPPORTED -#define PNG_READ_STRIP_ALPHA_SUPPORTED -#define PNG_READ_PACKSWAP_SUPPORTED +#define PNG_READ_sPLT_SUPPORTED #define PNG_READ_sRGB_SUPPORTED -#define PNG_WRITE_tEXt_SUPPORTED -#define PNG_READ_gAMA_SUPPORTED -#define PNG_READ_pCAL_SUPPORTED -#define PNG_READ_EXPAND_SUPPORTED -#define PNG_WRITE_sPLT_SUPPORTED +#define PNG_READ_STRIP_16_TO_8_SUPPORTED +#define PNG_READ_STRIP_ALPHA_SUPPORTED +#define PNG_READ_SUPPORTED +#define PNG_READ_SWAP_ALPHA_SUPPORTED #define PNG_READ_SWAP_SUPPORTED +#define PNG_READ_tEXt_SUPPORTED +#define PNG_READ_TEXT_SUPPORTED #define PNG_READ_tIME_SUPPORTED -#define PNG_READ_pHYs_SUPPORTED -#define PNG_WRITE_SWAP_ALPHA_SUPPORTED +#define PNG_READ_TRANSFORMS_SUPPORTED +#define PNG_READ_tRNS_SUPPORTED +#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_READ_USER_CHUNKS_SUPPORTED +#define PNG_READ_USER_TRANSFORM_SUPPORTED +#define PNG_READ_zTXt_SUPPORTED +#define PNG_SAVE_INT_32_SUPPORTED +#define PNG_sBIT_SUPPORTED +#define PNG_sCAL_SUPPORTED +#define PNG_SEQUENTIAL_READ_SUPPORTED +#define PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED +#define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED +#define PNG_SETJMP_SUPPORTED +#define PNG_SET_USER_LIMITS_SUPPORTED +#define PNG_sPLT_SUPPORTED +#define PNG_sRGB_SUPPORTED +#define PNG_STDIO_SUPPORTED +#define PNG_tEXt_SUPPORTED +#define PNG_TEXT_SUPPORTED #define PNG_TIME_RFC1123_SUPPORTED -#define PNG_READ_TEXT_SUPPORTED -#define PNG_WRITE_BGR_SUPPORTED +#define PNG_tIME_SUPPORTED +#define PNG_tRNS_SUPPORTED +#define PNG_UNKNOWN_CHUNKS_SUPPORTED #define PNG_USER_CHUNKS_SUPPORTED -#define PNG_CONSOLE_IO_SUPPORTED -#define PNG_WRITE_PACK_SUPPORTED -#define PNG_READ_FILLER_SUPPORTED +#define PNG_USER_LIMITS_SUPPORTED +#define PNG_USER_MEM_SUPPORTED +#define PNG_USER_TRANSFORM_INFO_SUPPORTED +#define PNG_USER_TRANSFORM_PTR_SUPPORTED +#define PNG_WARNINGS_SUPPORTED +#define PNG_WRITE_16BIT_SUPPORTED +#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_WRITE_BGR_SUPPORTED #define PNG_WRITE_bKGD_SUPPORTED -#define PNG_WRITE_tRNS_SUPPORTED -#define PNG_READ_sPLT_SUPPORTED -#define PNG_WRITE_sCAL_SUPPORTED +#define PNG_WRITE_cHRM_SUPPORTED +#define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED +#define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +#define PNG_WRITE_FILLER_SUPPORTED +#define PNG_WRITE_FILTER_SUPPORTED +#define PNG_WRITE_FLUSH_SUPPORTED +#define PNG_WRITE_gAMA_SUPPORTED +#define PNG_WRITE_hIST_SUPPORTED +#define PNG_WRITE_iCCP_SUPPORTED +#define PNG_WRITE_INTERLACING_SUPPORTED +#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED +#define PNG_WRITE_INVERT_ALPHA_SUPPORTED +#define PNG_WRITE_INVERT_SUPPORTED +#define PNG_WRITE_iTXt_SUPPORTED #define PNG_WRITE_oFFs_SUPPORTED -#define PNG_READ_tEXt_SUPPORTED +#define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED +#define PNG_WRITE_PACK_SUPPORTED +#define PNG_WRITE_PACKSWAP_SUPPORTED +#define PNG_WRITE_pCAL_SUPPORTED +#define PNG_WRITE_pHYs_SUPPORTED #define PNG_WRITE_sBIT_SUPPORTED -#define PNG_READ_INVERT_SUPPORTED -#define PNG_READ_16_TO_8_SUPPORTED -#define PNG_WRITE_cHRM_SUPPORTED -#define PNG_16BIT_SUPPORTED +#define PNG_WRITE_sCAL_SUPPORTED +#define PNG_WRITE_SHIFT_SUPPORTED +#define PNG_WRITE_sPLT_SUPPORTED +#define PNG_WRITE_sRGB_SUPPORTED +#define PNG_WRITE_SUPPORTED +#define PNG_WRITE_SWAP_ALPHA_SUPPORTED +#define PNG_WRITE_SWAP_SUPPORTED +#define PNG_WRITE_tEXt_SUPPORTED +#define PNG_WRITE_TEXT_SUPPORTED +#define PNG_WRITE_tIME_SUPPORTED +#define PNG_WRITE_TRANSFORMS_SUPPORTED +#define PNG_WRITE_tRNS_SUPPORTED +#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED #define PNG_WRITE_USER_TRANSFORM_SUPPORTED -#define PNG_READ_BGR_SUPPORTED -#define PNG_WRITE_PACKSWAP_SUPPORTED -#define PNG_WRITE_INVERT_ALPHA_SUPPORTED -#define PNG_sCAL_SUPPORTED +#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED #define PNG_WRITE_zTXt_SUPPORTED -#define PNG_sBIT_SUPPORTED -#define PNG_cHRM_SUPPORTED -#define PNG_bKGD_SUPPORTED -#define PNG_tRNS_SUPPORTED -#define PNG_WRITE_iTXt_SUPPORTED -#define PNG_oFFs_SUPPORTED -#define PNG_USER_TRANSFORM_PTR_SUPPORTED -#define PNG_USER_TRANSFORM_INFO_SUPPORTED -#define PNG_hIST_SUPPORTED -#define PNG_iCCP_SUPPORTED -#define PNG_sRGB_SUPPORTED -#define PNG_READ_zTXt_SUPPORTED -#define PNG_gAMA_SUPPORTED -#define PNG_pCAL_SUPPORTED -#define PNG_CHECK_cHRM_SUPPORTED -#define PNG_tIME_SUPPORTED -#define PNG_pHYs_SUPPORTED -#define PNG_READ_iTXt_SUPPORTED -#define PNG_TEXT_SUPPORTED -#define PNG_SAVE_INT_32_SUPPORTED -#define PNG_sPLT_SUPPORTED -#define PNG_tEXt_SUPPORTED #define PNG_zTXt_SUPPORTED -#define PNG_iTXt_SUPPORTED /* end of options */ #endif /* PNGLCONF_H */ diff --git a/src/3rdparty/libpng/pngmem.c b/src/3rdparty/libpng/pngmem.c index a15d8b0..ea606d6 100644 --- a/src/3rdparty/libpng/pngmem.c +++ b/src/3rdparty/libpng/pngmem.c @@ -1,7 +1,7 @@ /* pngmem.c - stub functions for memory allocation * - * Last changed in libpng 1.5.1 [February 3, 2011] + * Last changed in libpng 1.5.4 [July 7, 2011] * Copyright (c) 1998-2011 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -187,8 +187,9 @@ png_malloc_default,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) int num_blocks; png_uint_32 total_size; png_bytep table; - int i; + int i, mem_level, window_bits; png_byte huge * hptr; + int window_bits if (ret != NULL) { @@ -196,14 +197,22 @@ png_malloc_default,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) ret = NULL; } - if (png_ptr->zlib_window_bits > 14) - num_blocks = (int)(1 << (png_ptr->zlib_window_bits - 14)); + window_bits = + png_ptr->zlib_window_bits >= png_ptr->zlib_text_window_bits ? + png_ptr->zlib_window_bits : png_ptr->zlib_text_window_bits; + + if (window_bits > 14) + num_blocks = (int)(1 << (window_bits - 14)); else num_blocks = 1; - if (png_ptr->zlib_mem_level >= 7) - num_blocks += (int)(1 << (png_ptr->zlib_mem_level - 7)); + mem_level = + png_ptr->zlib_mem_level >= png_ptr->zlib_text_mem_level ? + png_ptr->zlib_mem_level : png_ptr->zlib_text_mem_level; + + if (mem_level >= 7) + num_blocks += (int)(1 << (mem_level - 7)); else num_blocks++; @@ -277,7 +286,7 @@ png_malloc_default,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) { # ifndef PNG_USER_MEM_SUPPORTED if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) - png_error(png_ptr, "Out of Memory"); /* Note "o" and "M" */ + png_error(png_ptr, "Out of Memory"); /* Note "O" and "M" */ else png_warning(png_ptr, "Out of Memory"); diff --git a/src/3rdparty/libpng/pngpread.c b/src/3rdparty/libpng/pngpread.c index 7b1149b..a50292a 100644 --- a/src/3rdparty/libpng/pngpread.c +++ b/src/3rdparty/libpng/pngpread.c @@ -1,7 +1,7 @@ /* pngpread.c - read a png file in push mode * - * Last changed in libpng 1.5.1 [February 3, 2011] + * Last changed in libpng 1.5.2 [March 31, 2011] * Copyright (c) 1998-2011 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -1026,8 +1026,10 @@ png_push_process_row(png_structp png_ptr) png_memcpy(png_ptr->prev_row, png_ptr->row_buf, png_ptr->rowbytes + 1); - if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA)) +#ifdef PNG_READ_TRANSFORMS_SUPPORTED + if (png_ptr->transformations) png_do_read_transformations(png_ptr); +#endif #ifdef PNG_READ_INTERLACING_SUPPORTED /* Blow up interlaced rows to full size */ @@ -1288,7 +1290,7 @@ png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 { PNG_UNUSED(info_ptr) /* To quiet some compiler warnings */ png_error(png_ptr, "Out of place tEXt"); - /*NOT REACHED*/ + /* NOT REACHED */ } #ifdef PNG_MAX_MALLOC_64K @@ -1385,7 +1387,7 @@ png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 { PNG_UNUSED(info_ptr) /* To quiet some compiler warnings */ png_error(png_ptr, "Out of place zTXt"); - /*NOT REACHED*/ + /* NOT REACHED */ } #ifdef PNG_MAX_MALLOC_64K @@ -1589,7 +1591,7 @@ png_push_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 { PNG_UNUSED(info_ptr) /* To quiet some compiler warnings */ png_error(png_ptr, "Out of place iTXt"); - /*NOT REACHED*/ + /* NOT REACHED */ } #ifdef PNG_MAX_MALLOC_64K diff --git a/src/3rdparty/libpng/pngpriv.h b/src/3rdparty/libpng/pngpriv.h index 9b90f26..ca2fb8c 100644 --- a/src/3rdparty/libpng/pngpriv.h +++ b/src/3rdparty/libpng/pngpriv.h @@ -6,7 +6,7 @@ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * - * Last changed in libpng 1.5.0 [January 6, 2011] + * Last changed in libpng 1.5.4 [July 7, 2011] * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -29,6 +29,20 @@ # define _CRT_SECURE_NO_DEPRECATE #endif +/* Feature Test Macros. The following are defined here to ensure that correctly + * implemented libraries reveal the APIs libpng needs to build and hide those + * that are not needed and potentially damaging to the compilation. + * + * Feature Test Macros must be defined before any system header is included (see + * POSIX 1003.1 2.8.2 "POSIX Symbols." + * + * These macros only have an effect if the operating system supports either + * POSIX 1003.1 or C99, or both. On other operating systems (particularly + * Windows/Visual Studio) there is no effect; the OS specific tests below are + * still required (as of 2011-05-02.) + */ +#define _POSIX_SOURCE 1 /* Just the POSIX 1003.1 and C89 APIs */ + /* This is required for the definition of abort(), used as a last ditch * error handler when all else fails. */ @@ -87,13 +101,15 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp; # define PNG_MAX_MALLOC_64K #endif +#ifndef PNG_UNUSED /* Unused formal parameter warnings are silenced using the following macro * which is expected to have no bad effects on performance (optimizing * compilers will probably remove it entirely). Note that if you replace * it with something other than whitespace, you must include the terminating * semicolon. */ -#define PNG_UNUSED(param) (void)param; +# define PNG_UNUSED(param) (void)param; +#endif /* Just a little check that someone hasn't tried to define something * contradictory. @@ -103,12 +119,27 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp; # define PNG_ZBUF_SIZE 65536L #endif -/* If warnings or errors are turned off the code is disabled - * or redirected here. +/* PNG_STATIC is used to mark internal file scope functions if they need to be + * accessed for implementation tests (see the code in tests/?*). */ -#ifndef PNG_WARNINGS_SUPPORTED -# define png_warning(s1,s2) ((void)0) -# define png_chunk_warning(s1,s2) ((void)0) +#ifndef PNG_STATIC +# define PNG_STATIC static +#endif + +/* If warnings or errors are turned off the code is disabled or redirected here. + * From 1.5.4 functions have been added to allow very limited formatting of + * error and warning messages - this code will also be disabled here. + */ +#ifdef PNG_WARNINGS_SUPPORTED +# define PNG_WARNING_PARAMETERS(p) png_warning_parameters p; +#else +# define png_warning(s1,s2) ((void)(s1)) +# define png_chunk_warning(s1,s2) ((void)(s1)) +# define png_warning_parameter(p,number,string) ((void)0) +# define png_warning_parameter_unsigned(p,number,format,value) ((void)0) +# define png_warning_parameter_signed(p,number,format,value) ((void)0) +# define png_formatted_warning(pp,p,message) ((void)(pp)) +# define PNG_WARNING_PARAMETERS(p) #endif #ifndef PNG_ERROR_TEXT_SUPPORTED # define png_error(s1,s2) png_err(s1) @@ -204,60 +235,28 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp; # define NOCHECK 0 # define CVT_PTR(ptr) (png_far_to_near(png_ptr,ptr,CHECK)) # define CVT_PTR_NOCHECK(ptr) (png_far_to_near(png_ptr,ptr,NOCHECK)) -# define png_strcpy _fstrcpy -# define png_strncpy _fstrncpy /* Added to v 1.2.6 */ # define png_strlen _fstrlen # define png_memcmp _fmemcmp /* SJT: added */ # define png_memcpy _fmemcpy # define png_memset _fmemset -# define png_sprintf sprintf #else # ifdef _WINDOWS_ /* Favor Windows over C runtime fns */ # define CVT_PTR(ptr) (ptr) # define CVT_PTR_NOCHECK(ptr) (ptr) -# define png_strcpy lstrcpyA -# define png_strncpy lstrcpynA # define png_strlen lstrlenA # define png_memcmp memcmp # define png_memcpy CopyMemory # define png_memset memset -# define png_sprintf wsprintfA # else # define CVT_PTR(ptr) (ptr) # define CVT_PTR_NOCHECK(ptr) (ptr) -# define png_strcpy strcpy -# define png_strncpy strncpy /* Added to v 1.2.6 */ # define png_strlen strlen # define png_memcmp memcmp /* SJT: added */ # define png_memcpy memcpy # define png_memset memset -# define png_sprintf sprintf # endif #endif /* End of memory model/platform independent support */ - -#ifndef PNG_NO_SNPRINTF -# ifdef _MSC_VER -# define png_snprintf _snprintf /* Added to v 1.2.19 */ -# define png_snprintf2 _snprintf -# define png_snprintf6 _snprintf -# else -# define png_snprintf snprintf /* Added to v 1.2.19 */ -# define png_snprintf2 snprintf -# define png_snprintf6 snprintf -# endif -#else - /* You don't have or don't want to use snprintf(). Caution: Using - * sprintf instead of snprintf exposes your application to accidental - * or malevolent buffer overflows. If you don't have snprintf() - * as a general rule you should provide one (you can get one from - * Portable OpenSSH). - */ -# define png_snprintf(s1,n,fmt,x1) png_sprintf(s1,fmt,x1) -# define png_snprintf2(s1,n,fmt,x1,x2) png_sprintf(s1,fmt,x1,x2) -# define png_snprintf6(s1,n,fmt,x1,x2,x3,x4,x5,x6) \ - png_sprintf(s1,fmt,x1,x2,x3,x4,x5,x6) -#endif /* End of 1.5.0beta36 move from pngconf.h */ /* CONSTANTS and UTILITY MACROS @@ -265,12 +264,14 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp; */ /* Various modes of operation. Note that after an init, mode is set to - * zero automatically when the structure is created. + * zero automatically when the structure is created. Three of these + * are defined in png.h because they need to be visible to applications + * that call png_set_unknown_chunk(). */ -#define PNG_HAVE_IHDR 0x01 -#define PNG_HAVE_PLTE 0x02 +/* #define PNG_HAVE_IHDR 0x01 (defined in png.h) */ +/* #define PNG_HAVE_PLTE 0x02 (defined in png.h) */ #define PNG_HAVE_IDAT 0x04 -#define PNG_AFTER_IDAT 0x08 /* Have complete zlib datastream */ +/* #define PNG_AFTER_IDAT 0x08 (defined in png.h) */ #define PNG_HAVE_IEND 0x10 #define PNG_HAVE_gAMA 0x20 #define PNG_HAVE_cHRM 0x40 @@ -290,10 +291,10 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp; #define PNG_SWAP_BYTES 0x0010 #define PNG_INVERT_MONO 0x0020 #define PNG_QUANTIZE 0x0040 -#define PNG_BACKGROUND 0x0080 +#define PNG_COMPOSE 0x0080 /* Was PNG_BACKGROUND */ #define PNG_BACKGROUND_EXPAND 0x0100 - /* 0x0200 unused */ -#define PNG_16_TO_8 0x0400 +#define PNG_EXPAND_16 0x0200 /* Added to libpng 1.5.2 */ +#define PNG_16_TO_8 0x0400 /* Becomes 'chop' in 1.5.4 */ #define PNG_RGBA 0x0800 #define PNG_EXPAND 0x1000 #define PNG_GAMMA 0x2000 @@ -307,10 +308,10 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp; #define PNG_RGB_TO_GRAY_ERR 0x200000L #define PNG_RGB_TO_GRAY_WARN 0x400000L #define PNG_RGB_TO_GRAY 0x600000L /* two bits, RGB_TO_GRAY_ERR|WARN */ - /* 0x800000L Unused */ +#define PNG_ENCODE_ALPHA 0x800000L /* Added to libpng-1.5.4 */ #define PNG_ADD_ALPHA 0x1000000L /* Added to libpng-1.2.7 */ #define PNG_EXPAND_tRNS 0x2000000L /* Added to libpng-1.2.9 */ - /* 0x4000000L unused */ +#define PNG_SCALE_16_TO_8 0x4000000L /* Added to libpng-1.5.4 */ /* 0x8000000L unused */ /* 0x10000000L unused */ /* 0x20000000L unused */ @@ -337,25 +338,25 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp; #define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200 #define PNG_FLAG_CRC_CRITICAL_USE 0x0400 #define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800 - /* 0x1000 unused */ - /* 0x2000 unused */ - /* 0x4000 unused */ +#define PNG_FLAG_ASSUME_sRGB 0x1000 /* Added to libpng-1.5.4 */ +#define PNG_FLAG_OPTIMIZE_ALPHA 0x2000 /* Added to libpng-1.5.4 */ +#define PNG_FLAG_DETECT_UNINITIALIZED 0x4000 /* Added to libpng-1.5.4 */ #define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000L #define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000L #define PNG_FLAG_LIBRARY_MISMATCH 0x20000L #define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000L #define PNG_FLAG_STRIP_ERROR_TEXT 0x80000L #define PNG_FLAG_MALLOC_NULL_MEM_OK 0x100000L -#define PNG_FLAG_ADD_ALPHA 0x200000L /* Added to libpng-1.2.8 */ -#define PNG_FLAG_STRIP_ALPHA 0x400000L /* Added to libpng-1.2.8 */ + /* 0x200000L unused */ + /* 0x400000L unused */ #define PNG_FLAG_BENIGN_ERRORS_WARN 0x800000L /* Added to libpng-1.4.0 */ - /* 0x1000000L unused */ - /* 0x2000000L unused */ - /* 0x4000000L unused */ - /* 0x8000000L unused */ - /* 0x10000000L unused */ - /* 0x20000000L unused */ - /* 0x40000000L unused */ +#define PNG_FLAG_ZTXT_CUSTOM_STRATEGY 0x1000000L /* 5 lines added */ +#define PNG_FLAG_ZTXT_CUSTOM_LEVEL 0x2000000L /* to libpng-1.5.4 */ +#define PNG_FLAG_ZTXT_CUSTOM_MEM_LEVEL 0x4000000L +#define PNG_FLAG_ZTXT_CUSTOM_WINDOW_BITS 0x8000000L +#define PNG_FLAG_ZTXT_CUSTOM_METHOD 0x10000000L + /* 0x20000000L unused */ + /* 0x40000000L unused */ #define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \ PNG_FLAG_CRC_ANCILLARY_NOWARN) @@ -464,6 +465,11 @@ PNG_EXTERN png_fixed_point png_fixed PNGARG((png_structp png_ptr, double fp, #define PNG_tRNS PNG_CONST png_byte png_tRNS[5] = {116, 82, 78, 83, '\0'} #define PNG_zTXt PNG_CONST png_byte png_zTXt[5] = {122, 84, 88, 116, '\0'} +/* Gamma values (new at libpng-1.5.4): */ +#define PNG_GAMMA_MAC_OLD 151724 /* Assume '1.8' is really 2.2/1.45! */ +#define PNG_GAMMA_MAC_INVERSE 65909 +#define PNG_GAMMA_sRGB_INVERSE 45455 + /* Inhibit C++ name-mangling for libpng functions but not for system calls. */ #ifdef __cplusplus @@ -476,6 +482,12 @@ extern "C" { * be found in the files where the functions are located. */ +/* Check the user version string for compatibility, returns false if the version + * numbers aren't compatible. + */ +PNG_EXTERN int png_user_version_check(png_structp png_ptr, + png_const_charp user_png_ver); + /* Allocate memory for an internal libpng struct */ PNG_EXTERN PNG_FUNCTION(png_voidp,png_create_struct,PNGARG((int type)), PNG_ALLOCATED); @@ -544,8 +556,7 @@ PNG_EXTERN void png_crc_read PNGARG((png_structp png_ptr, png_bytep buf, png_size_t length)); /* Decompress data in a chunk that uses compression */ -#if defined(PNG_zTXt_SUPPORTED) || defined(PNG_iTXt_SUPPORTED) || \ - defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) +#if defined(PNG_READ_COMPRESSED_TEXT_SUPPORTED) PNG_EXTERN void png_decompress_chunk PNGARG((png_structp png_ptr, int comp_type, png_size_t chunklength, png_size_t prefix_length, png_size_t *data_length)); @@ -648,6 +659,7 @@ PNG_EXTERN void png_write_hIST PNGARG((png_structp png_ptr, png_const_uint_16p hist, int num_hist)); #endif +/* Chunks that have keywords */ #if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) PNG_EXTERN png_size_t png_check_keyword PNGARG((png_structp png_ptr, @@ -738,17 +750,17 @@ PNG_EXTERN void png_read_filter_row PNGARG((png_structp png_ptr, PNG_EXTERN void png_write_find_filter PNGARG((png_structp png_ptr, png_row_infop row_info)); -/* Write out the filtered row. */ -PNG_EXTERN void png_write_filtered_row PNGARG((png_structp png_ptr, - png_bytep filtered_row)); /* Finish a row while reading, dealing with interlacing passes, etc. */ PNG_EXTERN void png_read_finish_row PNGARG((png_structp png_ptr)); /* Initialize the row buffers, etc. */ PNG_EXTERN void png_read_start_row PNGARG((png_structp png_ptr)); + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED /* Optional call to update the users info structure */ PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr, png_infop info_ptr)); +#endif /* These are the functions that do the transformations */ #ifdef PNG_READ_FILLER_SUPPORTED @@ -778,8 +790,8 @@ PNG_EXTERN void png_do_write_invert_alpha PNGARG((png_row_infop row_info, #if defined(PNG_WRITE_FILLER_SUPPORTED) || \ defined(PNG_READ_STRIP_ALPHA_SUPPORTED) -PNG_EXTERN void png_do_strip_filler PNGARG((png_row_infop row_info, - png_bytep row, png_uint_32 flags)); +PNG_EXTERN void png_do_strip_channel PNGARG((png_row_infop row_info, + png_bytep row, int at_start)); #endif #ifdef PNG_16BIT_SUPPORTED @@ -820,7 +832,12 @@ PNG_EXTERN void png_do_invert PNGARG((png_row_infop row_info, png_bytep row)); #endif -#ifdef PNG_READ_16_TO_8_SUPPORTED +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED +PNG_EXTERN void png_do_scale_16_to_8 PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED PNG_EXTERN void png_do_chop PNGARG((png_row_infop row_info, png_bytep row)); #endif @@ -851,26 +868,20 @@ PNG_EXTERN void png_do_shift PNGARG((png_row_infop row_info, png_bytep row, png_const_color_8p bit_depth)); #endif -#ifdef PNG_READ_BACKGROUND_SUPPORTED -# ifdef PNG_READ_GAMMA_SUPPORTED -PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, - png_bytep row, png_const_color_16p trans_color, - png_const_color_16p background, png_const_color_16p background_1, - png_const_bytep gamma_table, png_const_bytep gamma_from_1, - png_const_bytep gamma_to_1, png_const_uint_16pp gamma_16, - png_const_uint_16pp gamma_16_from_1, png_const_uint_16pp gamma_16_to_1, - int gamma_shift)); -# else -PNG_EXTERN void png_do_background PNGARG((png_row_infop row_info, - png_bytep row, png_const_color_16p trans_color, - png_const_color_16p background)); -# endif +#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) +PNG_EXTERN void png_do_compose PNGARG((png_row_infop row_info, + png_bytep row, png_structp png_ptr)); #endif #ifdef PNG_READ_GAMMA_SUPPORTED PNG_EXTERN void png_do_gamma PNGARG((png_row_infop row_info, - png_bytep row, png_const_bytep gamma_table, - png_const_uint_16pp gamma_16_table, int gamma_shift)); + png_bytep row, png_structp png_ptr)); +#endif + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED +PNG_EXTERN void png_do_encode_alpha PNGARG((png_row_infop row_info, + png_bytep row, png_structp png_ptr)); #endif #ifdef PNG_READ_EXPAND_SUPPORTED @@ -881,6 +892,11 @@ PNG_EXTERN void png_do_expand PNGARG((png_row_infop row_info, png_bytep row, png_const_color_16p trans_color)); #endif +#ifdef PNG_READ_EXPAND_16_SUPPORTED +PNG_EXTERN void png_do_expand_16 PNGARG((png_row_infop row_info, + png_bytep row)); +#endif + /* The following decodes the appropriate chunks, and does error correction, * then calls the appropriate callback for the chunk if it is valid. */ @@ -985,10 +1001,16 @@ PNG_EXTERN void png_check_chunk_name PNGARG((png_structp png_ptr, png_const_bytep chunk_name)); /* Handle the transformations for reading and writing */ +#ifdef PNG_READ_TRANSFORMS_SUPPORTED PNG_EXTERN void png_do_read_transformations PNGARG((png_structp png_ptr)); +#endif +#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED PNG_EXTERN void png_do_write_transformations PNGARG((png_structp png_ptr)); +#endif +#ifdef PNG_READ_TRANSFORMS_SUPPORTED PNG_EXTERN void png_init_read_transformations PNGARG((png_structp png_ptr)); +#endif #ifdef PNG_PROGRESSIVE_READ_SUPPORTED PNG_EXTERN void png_push_read_chunk PNGARG((png_structp png_ptr, @@ -1085,6 +1107,76 @@ PNG_EXTERN PNG_FUNCTION(void, png_fixed_error, (png_structp png_ptr, png_const_charp name),PNG_NORETURN); #endif +/* Puts 'string' into 'buffer' at buffer[pos], taking care never to overwrite + * the end. Always leaves the buffer nul terminated. Never errors out (and + * there is no error code.) + */ +PNG_EXTERN size_t png_safecat(png_charp buffer, size_t bufsize, size_t pos, + png_const_charp string); + +/* Various internal functions to handle formatted warning messages, currently + * only implemented for warnings. + */ +#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_TIME_RFC1123_SUPPORTED) +/* Utility to dump an unsigned value into a buffer, given a start pointer and + * and end pointer (which should point just *beyond* the end of the buffer!) + * Returns the pointer to the start of the formatted string. This utility only + * does unsigned values. + */ +PNG_EXTERN png_charp png_format_number(png_const_charp start, png_charp end, + int format, png_alloc_size_t number); + +/* Convenience macro that takes an array: */ +#define PNG_FORMAT_NUMBER(buffer,format,number) \ + png_format_number(buffer, buffer + (sizeof buffer), format, number) + +/* Suggested size for a number buffer (enough for 64 bits and a sign!) */ +#define PNG_NUMBER_BUFFER_SIZE 24 + +/* These are the integer formats currently supported, the name is formed from + * the standard printf(3) format string. + */ +#define PNG_NUMBER_FORMAT_u 1 /* chose unsigned API! */ +#define PNG_NUMBER_FORMAT_02u 2 +#define PNG_NUMBER_FORMAT_d 1 /* chose signed API! */ +#define PNG_NUMBER_FORMAT_02d 2 +#define PNG_NUMBER_FORMAT_x 3 +#define PNG_NUMBER_FORMAT_02x 4 +#define PNG_NUMBER_FORMAT_fixed 5 /* choose the signed API */ +#endif + +#ifdef PNG_WARNINGS_SUPPORTED +/* New defines and members adding in libpng-1.5.4 */ +# define PNG_WARNING_PARAMETER_SIZE 32 +# define PNG_WARNING_PARAMETER_COUNT 8 + +/* An l-value of this type has to be passed to the APIs below to cache the + * values of the parameters to a formatted warning message. + */ +typedef char png_warning_parameters[PNG_WARNING_PARAMETER_COUNT][ + PNG_WARNING_PARAMETER_SIZE]; + +PNG_EXTERN void png_warning_parameter(png_warning_parameters p, int number, + png_const_charp string); + /* Parameters are limited in size to PNG_WARNING_PARAMETER_SIZE characters, + * including the trailing '\0'. + */ +PNG_EXTERN void png_warning_parameter_unsigned(png_warning_parameters p, + int number, int format, png_alloc_size_t value); + /* Use png_alloc_size_t because it is an unsigned type as big as any we + * need to output. Use the following for a signed value. + */ +PNG_EXTERN void png_warning_parameter_signed(png_warning_parameters p, + int number, int format, png_int_32 value); + +PNG_EXTERN void png_formatted_warning(png_structp png_ptr, + png_warning_parameters p, png_const_charp message); + /* 'message' follows the X/Open approach of using @1, @2 to insert + * parameters previously supplied using the above functions. Errors in + * specifying the paramters will simple result in garbage substitutions. + */ +#endif + /* ASCII to FP interfaces, currently only implemented if sCAL * support is required. */ @@ -1147,8 +1239,18 @@ PNG_EXTERN void png_ascii_from_fixed PNGARG((png_structp png_ptr, #define PNG_FP_SAW_DOT 16 /* Saw a dot in current state */ #define PNG_FP_SAW_E 32 /* Saw an E (or e) in current state */ #define PNG_FP_SAW_ANY 60 /* Saw any of the above 4 */ + +/* These three values don't affect the parser. They are set but not used. + */ #define PNG_FP_WAS_VALID 64 /* Preceding substring is a valid fp number */ -#define PNG_FP_INVALID 128 /* Available for callers as a distinct value */ +#define PNG_FP_NEGATIVE 128 /* A negative number, including "-0" */ +#define PNG_FP_NONZERO 256 /* A non-zero value */ +#define PNG_FP_STICKY 448 /* The above three flags */ + +/* This is available for the caller to store in 'state' if required. Do not + * call the parser after setting it (the parser sometimes clears it.) + */ +#define PNG_FP_INVALID 512 /* Available for callers as a distinct value */ /* Result codes for the parser (boolean - true meants ok, false means * not ok yet.) @@ -1156,6 +1258,20 @@ PNG_EXTERN void png_ascii_from_fixed PNGARG((png_structp png_ptr, #define PNG_FP_MAYBE 0 /* The number may be valid in the future */ #define PNG_FP_OK 1 /* The number is valid */ +/* Tests on the sticky non-zero and negative flags. To pass these checks + * the state must also indicate that the whole number is valid - this is + * achieved by testing PNG_FP_SAW_DIGIT (see the implementation for why this + * is equivalent to PNG_FP_OK above.) + */ +#define PNG_FP_NZ_MASK (PNG_FP_SAW_DIGIT | PNG_FP_NEGATIVE | PNG_FP_NONZERO) + /* NZ_MASK: the string is valid and a non-zero negative value */ +#define PNG_FP_Z_MASK (PNG_FP_SAW_DIGIT | PNG_FP_NONZERO) + /* Z MASK: the string is valid and a non-zero value. */ + /* PNG_FP_SAW_DIGIT: the string is valid. */ +#define PNG_FP_IS_ZERO(state) (((state) & PNG_FP_Z_MASK) == PNG_FP_SAW_DIGIT) +#define PNG_FP_IS_POSITIVE(state) (((state) & PNG_FP_NZ_MASK) == PNG_FP_Z_MASK) +#define PNG_FP_IS_NEGATIVE(state) (((state) & PNG_FP_NZ_MASK) == PNG_FP_NZ_MASK) + /* The actual parser. This can be called repeatedly, it updates * the index into the string and the state variable (which must * be initialzed to 0). It returns a result code, as above. There @@ -1175,7 +1291,10 @@ PNG_EXTERN int png_check_fp_number PNGARG((png_const_charp string, png_size_t size, int *statep, png_size_tp whereami)); /* This is the same but it checks a complete string and returns true - * only if it just contains a floating point number. + * only if it just contains a floating point number. As of 1.5.4 this + * function also returns the state at the end of parsing the number if + * it was valid (otherwise it returns 0.) This can be used for testing + * for negative or zero values using the sticky flag. */ PNG_EXTERN int png_check_fp_string PNGARG((png_const_charp string, png_size_t size)); @@ -1190,13 +1309,13 @@ PNG_EXTERN int png_check_fp_string PNGARG((png_const_charp string, * holds the result. */ PNG_EXTERN int png_muldiv PNGARG((png_fixed_point_p res, png_fixed_point a, - png_int_32 times, png_int_32 div)); + png_int_32 multiplied_by, png_int_32 divided_by)); #endif #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED) /* Same deal, but issue a warning on overflow and return 0. */ PNG_EXTERN png_fixed_point png_muldiv_warn PNGARG((png_structp png_ptr, - png_fixed_point a, png_int_32 times, png_int_32 div)); + png_fixed_point a, png_int_32 multiplied_by, png_int_32 divided_by)); #endif #ifdef PNG_READ_GAMMA_SUPPORTED @@ -1223,12 +1342,12 @@ PNG_EXTERN png_fixed_point png_reciprocal2 PNGARG((png_fixed_point a, * correct bit value - 0..255 or 0..65535 as required. */ PNG_EXTERN png_uint_16 png_gamma_correct PNGARG((png_structp png_ptr, - unsigned int value, png_fixed_point gamma)); -PNG_EXTERN int png_gamma_significant PNGARG((png_fixed_point gamma)); + unsigned int value, png_fixed_point gamma_value)); +PNG_EXTERN int png_gamma_significant PNGARG((png_fixed_point gamma_value)); PNG_EXTERN png_uint_16 png_gamma_16bit_correct PNGARG((unsigned int value, - png_fixed_point gamma)); + png_fixed_point gamma_value)); PNG_EXTERN png_byte png_gamma_8bit_correct PNGARG((unsigned int value, - png_fixed_point gamma)); + png_fixed_point gamma_value)); PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr, int bit_depth)); #endif diff --git a/src/3rdparty/libpng/pngread.c b/src/3rdparty/libpng/pngread.c index 2c8f2cd..be3df47 100644 --- a/src/3rdparty/libpng/pngread.c +++ b/src/3rdparty/libpng/pngread.c @@ -1,7 +1,7 @@ /* pngread.c - read a PNG file * - * Last changed in libpng 1.5.1 [$RDATE%] + * Last changed in libpng 1.5.4 [July 7, 2011] * Copyright (c) 1998-2011 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -47,12 +47,10 @@ png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, #ifdef PNG_SETJMP_SUPPORTED #ifdef USE_FAR_KEYWORD - jmp_buf png_jmpbuf; + jmp_buf tmp_jmpbuf; #endif #endif - int i; - png_debug(1, "in png_create_read_struct"); #ifdef PNG_USER_MEM_SUPPORTED @@ -85,13 +83,13 @@ png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, encounter a png_error() will longjmp here. Since the jmpbuf is then meaningless we abort instead of returning. */ #ifdef USE_FAR_KEYWORD - if (setjmp(png_jmpbuf)) + if (setjmp(tmp_jmpbuf)) #else if (setjmp(png_jmpbuf(png_ptr))) /* Sets longjmp to match setjmp */ #endif PNG_ABORT(); #ifdef USE_FAR_KEYWORD - png_memcpy(png_jmpbuf(png_ptr), png_jmpbuf, png_sizeof(jmp_buf)); + png_memcpy(png_jmpbuf(png_ptr), tmp_jmpbuf, png_sizeof(jmp_buf)); #endif #endif /* PNG_SETJMP_SUPPORTED */ @@ -101,54 +99,9 @@ png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); - if (user_png_ver) - { - i = 0; - - do - { - if (user_png_ver[i] != png_libpng_ver[i]) - png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; - } while (png_libpng_ver[i++]); - } - - else - png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; - - - if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) - { - /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so - * we must recompile any applications that use any older library version. - * For versions after libpng 1.0, we will be compatible, so we need - * only check the first digit. - */ - if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || - (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || - (user_png_ver[0] == '0' && user_png_ver[2] < '9')) - { -#ifdef PNG_CONSOLE_IO_SUPPORTED - char msg[80]; - if (user_png_ver) - { - png_snprintf2(msg, 80, - "Application built with libpng-%.20s" - " but running with %.20s", - user_png_ver, - png_libpng_ver); - png_warning(png_ptr, msg); - } -#else - png_warning(png_ptr, - "Incompatible libpng version in application and library"); -#endif -#ifdef PNG_ERROR_NUMBERS_SUPPORTED - png_ptr->flags = 0; -#endif - - png_cleanup_needed = 1; - } - } + /* Call the general version checker (shared with read and write code): */ + if (!png_user_version_check(png_ptr, user_png_ver)) + png_cleanup_needed = 1; if (!png_cleanup_needed) { @@ -457,7 +410,11 @@ png_read_update_info(png_structp png_ptr, png_infop info_ptr) "Ignoring extra png_read_update_info() call;" " row buffer not reallocated"); +#ifdef PNG_READ_TRANSFORMS_SUPPORTED png_read_transform_info(png_ptr, info_ptr); +#else + PNG_UNUSED(info_ptr) +#endif } #ifdef PNG_SEQUENTIAL_READ_SUPPORTED @@ -488,9 +445,11 @@ void PNGAPI png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row) { PNG_IDAT; +#ifdef PNG_READ_INTERLACING_SUPPORTED PNG_CONST int png_pass_dsp_mask[7] = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff}; PNG_CONST int png_pass_mask[7] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff}; +#endif int ret; if (png_ptr == NULL) @@ -702,8 +661,10 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row) #endif - if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA)) +#ifdef PNG_READ_TRANSFORMS_SUPPORTED + if (png_ptr->transformations) png_do_read_transformations(png_ptr); +#endif #ifdef PNG_READ_INTERLACING_SUPPORTED /* Blow up interlaced rows to full size */ @@ -1161,7 +1122,9 @@ png_read_destroy(png_structp png_ptr, png_infop info_ptr, jmp_buf tmp_jmp; #endif png_error_ptr error_fn; +#ifdef PNG_WARNINGS_SUPPORTED png_error_ptr warning_fn; +#endif png_voidp error_ptr; #ifdef PNG_USER_MEM_SUPPORTED png_free_ptr free_fn; @@ -1247,10 +1210,6 @@ png_read_destroy(png_structp png_ptr, png_infop info_ptr, #endif #endif -#ifdef PNG_TIME_RFC1123_SUPPORTED - png_free(png_ptr, png_ptr->time_buffer); -#endif - inflateEnd(&png_ptr->zstream); #ifdef PNG_PROGRESSIVE_READ_SUPPORTED @@ -1267,11 +1226,13 @@ png_read_destroy(png_structp png_ptr, png_infop info_ptr, * being used again. */ #ifdef PNG_SETJMP_SUPPORTED - png_memcpy(tmp_jmp, png_ptr->png_jmpbuf, png_sizeof(jmp_buf)); + png_memcpy(tmp_jmp, png_ptr->longjmp_buffer, png_sizeof(jmp_buf)); #endif error_fn = png_ptr->error_fn; +#ifdef PNG_WARNINGS_SUPPORTED warning_fn = png_ptr->warning_fn; +#endif error_ptr = png_ptr->error_ptr; #ifdef PNG_USER_MEM_SUPPORTED free_fn = png_ptr->free_fn; @@ -1280,14 +1241,16 @@ png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_memset(png_ptr, 0, png_sizeof(png_struct)); png_ptr->error_fn = error_fn; +#ifdef PNG_WARNINGS_SUPPORTED png_ptr->warning_fn = warning_fn; +#endif png_ptr->error_ptr = error_ptr; #ifdef PNG_USER_MEM_SUPPORTED png_ptr->free_fn = free_fn; #endif #ifdef PNG_SETJMP_SUPPORTED - png_memcpy(png_ptr->png_jmpbuf, tmp_jmp, png_sizeof(jmp_buf)); + png_memcpy(png_ptr->longjmp_buffer, tmp_jmp, png_sizeof(jmp_buf)); #endif } @@ -1311,7 +1274,7 @@ png_read_png(png_structp png_ptr, png_infop info_ptr, { int row; - if (png_ptr == NULL) + if (png_ptr == NULL || info_ptr == NULL) return; /* png_read_info() gives us all of the information from the @@ -1323,8 +1286,22 @@ png_read_png(png_structp png_ptr, png_infop info_ptr, /* -------------- image transformations start here ------------------- */ -#ifdef PNG_READ_16_TO_8_SUPPORTED - /* Tell libpng to strip 16 bit/color files down to 8 bits per color. +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED + /* Tell libpng to strip 16-bit/color files down to 8 bits per color. + */ + if (transforms & PNG_TRANSFORM_SCALE_16) + { + /* Added at libpng-1.5.4. "strip_16" produces the same result that it + * did in earlier versions, while "scale_16" is now more accurate. + */ + png_set_scale_16(png_ptr); + } +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED + /* If both SCALE and STRIP are required pngrtran will effectively cancel the + * latter by doing SCALE first. This is ok and allows apps not to check for + * which is supported to get the right answer. */ if (transforms & PNG_TRANSFORM_STRIP_16) png_set_strip_16(png_ptr); @@ -1405,7 +1382,7 @@ png_read_png(png_structp png_ptr, png_infop info_ptr, #endif #ifdef PNG_READ_SWAP_SUPPORTED - /* Swap bytes of 16 bit files to least significant byte first */ + /* Swap bytes of 16-bit files to least significant byte first */ if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) png_set_swap(png_ptr); #endif @@ -1424,8 +1401,19 @@ png_read_png(png_structp png_ptr, png_infop info_ptr, png_set_gray_to_rgb(png_ptr); #endif +/* Added at libpng-1.5.4 */ +#ifdef PNG_READ_EXPAND_16_SUPPORTED + if (transforms & PNG_TRANSFORM_EXPAND_16) + png_set_expand_16(png_ptr); +#endif + /* We don't handle adding filler bytes */ + /* We use png_read_image and rely on that for interlace handling, but we also + * call png_read_update_info therefore must turn on interlace handling now: + */ + (void)png_set_interlace_handling(png_ptr); + /* Optional call to gamma correct and add the background to the palette * and update info structure. REQUIRED if you are expecting libpng to * update the palette for you (i.e., you selected such a transform above). diff --git a/src/3rdparty/libpng/pngrtran.c b/src/3rdparty/libpng/pngrtran.c index e6e0c46..4e0401a 100644 --- a/src/3rdparty/libpng/pngrtran.c +++ b/src/3rdparty/libpng/pngrtran.c @@ -1,7 +1,7 @@ /* pngrtran.c - transforms the data in a row for PNG readers * - * Last changed in libpng 1.5.1 [February 3, 2011] + * Last changed in libpng 1.5.4 [July 7, 2011] * Copyright (c) 1998-2011 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -106,12 +106,18 @@ png_set_background_fixed(png_structp png_ptr, return; } - png_ptr->transformations |= PNG_BACKGROUND; + png_ptr->transformations |= PNG_COMPOSE | PNG_STRIP_ALPHA; + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + png_memcpy(&(png_ptr->background), background_color, png_sizeof(png_color_16)); png_ptr->background_gamma = background_gamma; png_ptr->background_gamma_type = (png_byte)(background_gamma_code); - png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0); + if (need_expand) + png_ptr->transformations |= PNG_BACKGROUND_EXPAND; + else + png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND; } # ifdef PNG_FLOATING_POINT_SUPPORTED @@ -126,8 +132,25 @@ png_set_background(png_structp png_ptr, # endif /* FLOATING_POINT */ #endif /* READ_BACKGROUND */ -#ifdef PNG_READ_16_TO_8_SUPPORTED -/* Strip 16 bit depth files to 8 bit depth */ +/* Scale 16-bit depth files to 8-bit depth. If both of these are set then the + * one that pngrtran does first (scale) happens. This is necessary to allow the + * TRANSFORM and API behavior to be somewhat consistent, and it's simpler. + */ +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED +void PNGAPI +png_set_scale_16(png_structp png_ptr) +{ + png_debug(1, "in png_set_scale_16"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= PNG_SCALE_16_TO_8; +} +#endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED +/* Chop 16-bit depth files to 8-bit depth */ void PNGAPI png_set_strip_16(png_structp png_ptr) { @@ -149,12 +172,194 @@ png_set_strip_alpha(png_structp png_ptr) if (png_ptr == NULL) return; - png_ptr->flags |= PNG_FLAG_STRIP_ALPHA; + png_ptr->transformations |= PNG_STRIP_ALPHA; } #endif +#if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED) +static png_fixed_point +translate_gamma_flags(png_structp png_ptr, png_fixed_point output_gamma, + int is_screen) +{ + /* Check for flag values. The main reason for having the old Mac value as a + * flag is that it is pretty near impossible to work out what the correct + * value is from Apple documentation - a working Mac system is needed to + * discover the value! + */ + if (output_gamma == PNG_DEFAULT_sRGB || + output_gamma == PNG_FP_1 / PNG_DEFAULT_sRGB) + { + /* If there is no sRGB support this just sets the gamma to the standard + * sRGB value. (This is a side effect of using this function!) + */ +# ifdef PNG_READ_sRGB_SUPPORTED + png_ptr->flags |= PNG_FLAG_ASSUME_sRGB; +# endif + if (is_screen) + output_gamma = PNG_GAMMA_sRGB; + else + output_gamma = PNG_GAMMA_sRGB_INVERSE; + } + + else if (output_gamma == PNG_GAMMA_MAC_18 || + output_gamma == PNG_FP_1 / PNG_GAMMA_MAC_18) + { + if (is_screen) + output_gamma = PNG_GAMMA_MAC_OLD; + else + output_gamma = PNG_GAMMA_MAC_INVERSE; + } + + return output_gamma; +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +static png_fixed_point +convert_gamma_value(png_structp png_ptr, double output_gamma) +{ + /* The following silently ignores cases where fixed point (times 100,000) + * gamma values are passed to the floating point API. This is safe and it + * means the fixed point constants work just fine with the floating point + * API. The alternative would just lead to undetected errors and spurious + * bug reports. Negative values fail inside the _fixed API unless they + * correspond to the flag values. + */ + if (output_gamma > 0 && output_gamma < 128) + output_gamma *= PNG_FP_1; + + /* This preserves -1 and -2 exactly: */ + output_gamma = floor(output_gamma + .5); + + if (output_gamma > PNG_FP_MAX || output_gamma < PNG_FP_MIN) + png_fixed_error(png_ptr, "gamma value"); + + return (png_fixed_point)output_gamma; +} +# endif +#endif /* READ_ALPHA_MODE || READ_GAMMA */ + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED +void PNGFAPI +png_set_alpha_mode_fixed(png_structp png_ptr, int mode, + png_fixed_point output_gamma) +{ + int compose = 0; + png_fixed_point file_gamma; + + png_debug(1, "in png_set_alpha_mode"); + + if (png_ptr == NULL) + return; + + output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/); + + /* Validate the value to ensure it is in a reasonable range. The value + * is expected to be 1 or greater, but this range test allows for some + * viewing correction values. The intent is to weed out users of this API + * who use the inverse of the gamma value accidentally! Since some of these + * values are reasonable this may have to be changed. + */ + if (output_gamma < 70000 || output_gamma > 300000) + png_error(png_ptr, "output gamma out of expected range"); + + /* The default file gamma is the inverse of the output gamma; the output + * gamma may be changed below so get the file value first: + */ + file_gamma = png_reciprocal(output_gamma); + + /* There are really 8 possibilities here, composed of any combination + * of: + * + * premultiply the color channels + * do not encode non-opaque pixels + * encode the alpha as well as the color channels + * + * The differences disappear if the input/output ('screen') gamma is 1.0, + * because then the encoding is a no-op and there is only the choice of + * premultiplying the color channels or not. + * + * png_set_alpha_mode and png_set_background interact because both use + * png_compose to do the work. Calling both is only useful when + * png_set_alpha_mode is used to set the default mode - PNG_ALPHA_PNG - along + * with a default gamma value. Otherwise PNG_COMPOSE must not be set. + */ + switch (mode) + { + case PNG_ALPHA_PNG: /* default: png standard */ + /* No compose, but it may be set by png_set_background! */ + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + break; + + case PNG_ALPHA_ASSOCIATED: /* color channels premultiplied */ + compose = 1; + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + /* The output is linear: */ + output_gamma = PNG_FP_1; + break; + + case PNG_ALPHA_OPTIMIZED: /* associated, non-opaque pixels linear */ + compose = 1; + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags |= PNG_FLAG_OPTIMIZE_ALPHA; + /* output_gamma records the encoding of opaque pixels! */ + break; + + case PNG_ALPHA_BROKEN: /* associated, non-linear, alpha encoded */ + compose = 1; + png_ptr->transformations |= PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + break; + + default: + png_error(png_ptr, "invalid alpha mode"); + } + + /* Only set the default gamma if the file gamma has not been set (this has + * the side effect that the gamma in a second call to png_set_alpha_mode will + * be ignored.) + */ + if (png_ptr->gamma == 0) + png_ptr->gamma = file_gamma; + + /* But always set the output gamma: */ + png_ptr->screen_gamma = output_gamma; + + /* Finally, if pre-multiplying, set the background fields to achieve the + * desired result. + */ + if (compose) + { + /* And obtain alpha pre-multiplication by composing on black: */ + png_memset(&png_ptr->background, 0, sizeof png_ptr->background); + png_ptr->background_gamma = png_ptr->gamma; /* just in case */ + png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_FILE; + png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND; + + if (png_ptr->transformations & PNG_COMPOSE) + png_error(png_ptr, + "conflicting calls to set alpha mode and background"); + + png_ptr->transformations |= PNG_COMPOSE; + } + + /* New API, make sure apps call the correct initializers: */ + png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED; +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void PNGAPI +png_set_alpha_mode(png_structp png_ptr, int mode, double output_gamma) +{ + png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr, + output_gamma)); +} +# endif +#endif + #ifdef PNG_READ_QUANTIZE_SUPPORTED -/* Dither file to 8 bit. Supply a palette, the current number +/* Dither file to 8-bit. Supply a palette, the current number * of elements in the palette, the maximum number of elements * allowed, and a histogram if possible. If the current number * of colors is greater then the maximum number, the palette will be @@ -560,30 +765,6 @@ png_set_quantize(png_structp png_ptr, png_colorp palette, #endif /* PNG_READ_QUANTIZE_SUPPORTED */ #ifdef PNG_READ_GAMMA_SUPPORTED -/* Transform the image from the file_gamma to the screen_gamma. We - * only do transformations on images where the file_gamma and screen_gamma - * are not close reciprocals, otherwise it slows things down slightly, and - * also needlessly introduces small errors. - * - * We will turn off gamma transformation later if no semitransparent entries - * are present in the tRNS array for palette images. We can't do it here - * because we don't necessarily have the tRNS chunk yet. - */ -static int /* PRIVATE */ -png_gamma_threshold(png_fixed_point scrn_gamma, png_fixed_point file_gamma) -{ - /* PNG_GAMMA_THRESHOLD is the threshold for performing gamma - * correction as a difference of the overall transform from 1.0 - * - * We want to compare the threshold with s*f - 1, if we get - * overflow here it is because of wacky gamma values so we - * turn on processing anyway. - */ - png_fixed_point gtest; - return !png_muldiv(>est, scrn_gamma, file_gamma, PNG_FP_1) || - png_gamma_significant(gtest); -} - void PNGFAPI png_set_gamma_fixed(png_structp png_ptr, png_fixed_point scrn_gamma, png_fixed_point file_gamma) @@ -593,10 +774,32 @@ png_set_gamma_fixed(png_structp png_ptr, png_fixed_point scrn_gamma, if (png_ptr == NULL) return; - if ((png_ptr->color_type & PNG_COLOR_MASK_ALPHA) || - (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) || - png_gamma_threshold(scrn_gamma, file_gamma)) - png_ptr->transformations |= PNG_GAMMA; + /* New in libpng-1.5.4 - reserve particular negative values as flags. */ + scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/); + file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/); + +#if PNG_LIBPNG_VER >= 10600 + /* Checking the gamma values for being >0 was added in 1.5.4 along with the + * premultiplied alpha support; this actually hides an undocumented feature + * of the previous implementation which allowed gamma processing to be + * disabled in background handling. There is no evidence (so far) that this + * was being used; however, png_set_background itself accepted and must still + * accept '0' for the gamma value it takes, because it isn't always used. + * + * Since this is an API change (albeit a very minor one that removes an + * undocumented API feature) it will not be made until libpng-1.6.0. + */ + if (file_gamma <= 0) + png_error(png_ptr, "invalid file gamma in png_set_gamma"); + + if (scrn_gamma <= 0) + png_error(png_ptr, "invalid screen gamma in png_set_gamma"); +#endif + + /* Set the gamma values unconditionally - this overrides the value in the PNG + * file if a gAMA chunk was present. png_set_alpha_mode provides a + * different, easier, way to default the file gamma. + */ png_ptr->gamma = file_gamma; png_ptr->screen_gamma = scrn_gamma; } @@ -605,9 +808,8 @@ png_set_gamma_fixed(png_structp png_ptr, png_fixed_point scrn_gamma, void PNGAPI png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma) { - png_set_gamma_fixed(png_ptr, - png_fixed(png_ptr, scrn_gamma, "png_set_gamma screen gamma"), - png_fixed(png_ptr, file_gamma, "png_set_gamma file gamma")); + png_set_gamma_fixed(png_ptr, convert_gamma_value(png_ptr, scrn_gamma), + convert_gamma_value(png_ptr, file_gamma)); } # endif /* FLOATING_POINT_SUPPORTED */ #endif /* READ_GAMMA */ @@ -686,6 +888,26 @@ png_set_tRNS_to_alpha(png_structp png_ptr) } #endif /* defined(PNG_READ_EXPAND_SUPPORTED) */ +#ifdef PNG_READ_EXPAND_16_SUPPORTED +/* Expand to 16-bit channels, expand the tRNS chunk too (because otherwise + * it may not work correctly.) + */ +void PNGAPI +png_set_expand_16(png_structp png_ptr) +{ + png_debug(1, "in png_set_expand_16"); + + if (png_ptr == NULL) + return; + + png_ptr->transformations |= (PNG_EXPAND_16 | PNG_EXPAND | PNG_EXPAND_tRNS); + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; + + /* New API, make sure apps call the correct initializers: */ + png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED; +} +#endif + #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED void PNGAPI png_set_gray_to_rgb(png_structp png_ptr) @@ -742,30 +964,38 @@ png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action, } #endif { - png_uint_16 red_int, green_int; - if (red < 0 || green < 0) + if (red >= 0 && green >= 0 && red + green <= PNG_FP_1) { - red_int = 6968; /* .212671 * 32768 + .5 */ - green_int = 23434; /* .715160 * 32768 + .5 */ - } + png_uint_16 red_int, green_int; - else if (red + green < 100000L) - { red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L); green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L); + + png_ptr->rgb_to_gray_red_coeff = red_int; + png_ptr->rgb_to_gray_green_coeff = green_int; + png_ptr->rgb_to_gray_blue_coeff = + (png_uint_16)(32768 - red_int - green_int); } else { - png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients"); - red_int = 6968; - green_int = 23434; - } + if (red >= 0 && green >= 0) + png_warning(png_ptr, + "ignoring out of range rgb_to_gray coefficients"); - png_ptr->rgb_to_gray_red_coeff = red_int; - png_ptr->rgb_to_gray_green_coeff = green_int; - png_ptr->rgb_to_gray_blue_coeff = - (png_uint_16)(32768 - red_int - green_int); + /* Use the defaults, from the cHRM chunk if set, else the built in Rec + * 709 values (which correspond to sRGB, so we don't have to worry + * about the sRGB chunk!) + */ + if (png_ptr->rgb_to_gray_red_coeff == 0 && + png_ptr->rgb_to_gray_green_coeff == 0 && + png_ptr->rgb_to_gray_blue_coeff == 0) + { + png_ptr->rgb_to_gray_red_coeff = 6968; /* .212671 * 32768 + .5 */ + png_ptr->rgb_to_gray_green_coeff = 23434; /* .715160 * 32768 + .5 */ + png_ptr->rgb_to_gray_blue_coeff = 2366; + } + } } } @@ -807,55 +1037,160 @@ png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr } #endif +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +#ifdef PNG_READ_GAMMA_SUPPORTED +/* In the case of gamma transformations only do transformations on images where + * the [file] gamma and screen_gamma are not close reciprocals, otherwise it + * slows things down slightly, and also needlessly introduces small errors. + */ +static int /* PRIVATE */ +png_gamma_threshold(png_fixed_point screen_gamma, png_fixed_point file_gamma) +{ + /* PNG_GAMMA_THRESHOLD is the threshold for performing gamma + * correction as a difference of the overall transform from 1.0 + * + * We want to compare the threshold with s*f - 1, if we get + * overflow here it is because of wacky gamma values so we + * turn on processing anyway. + */ + png_fixed_point gtest; + return !png_muldiv(>est, screen_gamma, file_gamma, PNG_FP_1) || + png_gamma_significant(gtest); +} +#endif + /* Initialize everything needed for the read. This includes modifying * the palette. */ -void /* PRIVATE */ -png_init_read_transformations(png_structp png_ptr) + +/*For the moment 'png_init_palette_transformations' and + * 'png_init_rgb_transformations' only do some flag canceling optimizations. + * The intent is that these two routines should have palette or rgb operations + * extracted from 'png_init_read_transformations'. + */ +static void /* PRIVATE */ +png_init_palette_transformations(png_structp png_ptr) { - png_debug(1, "in png_init_read_transformations"); + /* Called to handle the (input) palette case. In png_do_read_transformations + * the first step is to expand the palette if requested, so this code must + * take care to only make changes that are invariant with respect to the + * palette expansion, or only do them if there is no expansion. + * + * STRIP_ALPHA has already been handled in the caller (by setting num_trans + * to 0.) + */ + int input_has_alpha = 0; + int input_has_transparency = 0; - { -#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ - defined(PNG_READ_SHIFT_SUPPORTED) || \ - defined(PNG_READ_GAMMA_SUPPORTED) - int color_type = png_ptr->color_type; -#endif + if (png_ptr->num_trans > 0) + { + int i; + + /* Ignore if all the entries are opaque (unlikely!) */ + for (i=0; i<png_ptr->num_trans; ++i) + if (png_ptr->trans_alpha[i] == 255) + continue; + else if (png_ptr->trans_alpha[i] == 0) + input_has_transparency = 1; + else + input_has_alpha = 1; + } + + /* If no alpha we can optimize. */ + if (!input_has_alpha) + { + /* Any alpha means background and associative alpha processing is + * required, however if the alpha is 0 or 1 throughout OPTIIMIZE_ALPHA + * and ENCODE_ALPHA are irrelevant. + */ + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + + if (!input_has_transparency) + png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND); + } #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) + /* png_set_background handling - deals with the complexity of whether the + * background color is in the file format or the screen format in the case + * where an 'expand' will happen. + */ -#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED - /* Detect gray background and attempt to enable optimization - * for gray --> RGB case - * - * Note: if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or - * RGB_ALPHA (in which case need_expand is superfluous anyway), the - * background color might actually be gray yet not be flagged as such. - * This is not a problem for the current code, which uses - * PNG_BACKGROUND_IS_GRAY only to decide when to do the - * png_do_gray_to_rgb() transformation. + /* The following code cannot be entered in the alpha pre-multiplication case + * because PNG_BACKGROUND_EXPAND is cancelled below. */ if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && - !(color_type & PNG_COLOR_MASK_COLOR)) + (png_ptr->transformations & PNG_EXPAND)) { - png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; - } + { + png_ptr->background.red = + png_ptr->palette[png_ptr->background.index].red; + png_ptr->background.green = + png_ptr->palette[png_ptr->background.index].green; + png_ptr->background.blue = + png_ptr->palette[png_ptr->background.index].blue; - else if ((png_ptr->transformations & PNG_BACKGROUND) && - !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) && - (png_ptr->transformations & PNG_GRAY_TO_RGB) && - png_ptr->background.red == png_ptr->background.green && - png_ptr->background.red == png_ptr->background.blue) +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED + if (png_ptr->transformations & PNG_INVERT_ALPHA) + { + if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) + { + /* Invert the alpha channel (in tRNS) unless the pixels are + * going to be expanded, in which case leave it for later + */ + int i, istop = png_ptr->num_trans; + + for (i=0; i<istop; i++) + png_ptr->trans_alpha[i] = (png_byte)(255 - + png_ptr->trans_alpha[i]); + } + } +#endif /* PNG_READ_INVERT_ALPHA_SUPPORTED */ + } + } /* background expand and (therefore) no alpha association. */ +#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */ +} + +static void /* PRIVATE */ +png_init_rgb_transformations(png_structp png_ptr) +{ + /* Added to libpng-1.5.4: check the color type to determine whether there + * is any alpha or transparency in the image and simply cancel the + * background and alpha mode stuff if there isn't. + */ + int input_has_alpha = (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0; + int input_has_transparency = png_ptr->num_trans > 0; + + /* If no alpha we can optimize. */ + if (!input_has_alpha) { - png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; - png_ptr->background.gray = png_ptr->background.red; + /* Any alpha means background and associative alpha processing is + * required, however if the alpha is 0 or 1 throughout OPTIIMIZE_ALPHA + * and ENCODE_ALPHA are irrelevant. + */ +# ifdef PNG_READ_ALPHA_MODE_SUPPORTED + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; +# endif + + if (!input_has_transparency) + png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND); } -#endif +#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) + /* png_set_background handling - deals with the complexity of whether the + * background color is in the file format or the screen format in the case + * where an 'expand' will happen. + */ + + /* The following code cannot be entered in the alpha pre-multiplication case + * because PNG_BACKGROUND_EXPAND is cancelled below. + */ if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && - (png_ptr->transformations & PNG_EXPAND)) + (png_ptr->transformations & PNG_EXPAND) && + !(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) + /* i.e., GRAY or GRAY_ALPHA */ { - if (!(color_type & PNG_COLOR_MASK_COLOR)) /* i.e., GRAY or GRAY_ALPHA */ { /* Expand background and tRNS chunks */ switch (png_ptr->bit_depth) @@ -906,68 +1241,286 @@ png_init_read_transformations(png_structp png_ptr) break; } } - else if (color_type == PNG_COLOR_TYPE_PALETTE) - { - png_ptr->background.red = - png_ptr->palette[png_ptr->background.index].red; - png_ptr->background.green = - png_ptr->palette[png_ptr->background.index].green; - png_ptr->background.blue = - png_ptr->palette[png_ptr->background.index].blue; + } /* background expand and (therefore) no alpha association. */ +#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */ +} -#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED - if (png_ptr->transformations & PNG_INVERT_ALPHA) - { -#ifdef PNG_READ_EXPAND_SUPPORTED - if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) -#endif - { - /* Invert the alpha channel (in tRNS) unless the pixels are - * going to be expanded, in which case leave it for later - */ - int i, istop; - istop=(int)png_ptr->num_trans; - for (i=0; i<istop; i++) - png_ptr->trans_alpha[i] = (png_byte)(255 - - png_ptr->trans_alpha[i]); - } - } -#endif +void /* PRIVATE */ +png_init_read_transformations(png_structp png_ptr) +{ + png_debug(1, "in png_init_read_transformations"); + /* This internal function is called from png_read_start_row in pngrutil.c + * and it is called before the 'rowbytes' calculation is done, so the code + * in here can change or update the transformations flags. + * + * First do updates that do not depend on the details of the PNG image data + * being processed. + */ + +#ifdef PNG_READ_GAMMA_SUPPORTED + /* Prior to 1.5.4 these tests were performed from png_set_gamma, 1.5.4 adds + * png_set_alpha_mode and this is another source for a default file gamma so + * the test needs to be performed later - here. In addition prior to 1.5.4 + * the tests were repeated for the PALETTE color type here - this is no + * longer necessary (and doesn't seem to have been necessary before.) + */ + { + /* The following temporary indicates if overall gamma correction is + * required. + */ + int gamma_correction = 0; + + if (png_ptr->gamma != 0) /* has been set */ + { + if (png_ptr->screen_gamma != 0) /* screen set too */ + gamma_correction = png_gamma_threshold(png_ptr->gamma, + png_ptr->screen_gamma); + + else + /* Assume the output matches the input; a long time default behavior + * of libpng, although the standard has nothing to say about this. + */ + png_ptr->screen_gamma = png_reciprocal(png_ptr->gamma); } + + else if (png_ptr->screen_gamma != 0) + /* The converse - assume the file matches the screen, note that this + * perhaps undesireable default can (from 1.5.4) be changed by calling + * png_set_alpha_mode (even if the alpha handling mode isn't required + * or isn't changed from the default.) + */ + png_ptr->gamma = png_reciprocal(png_ptr->screen_gamma); + + else /* neither are set */ + /* Just in case the following prevents any processing - file and screen + * are both assumed to be linear and there is no way to introduce a + * third gamma value other than png_set_background with 'UNIQUE', and, + * prior to 1.5.4 + */ + png_ptr->screen_gamma = png_ptr->gamma = PNG_FP_1; + + /* Now turn the gamma transformation on or off as appropriate. Notice + * that PNG_GAMMA just refers to the file->screen correction. Alpha + * composition may independently cause gamma correction because it needs + * linear data (e.g. if the file has a gAMA chunk but the screen gamma + * hasn't been specified.) In any case this flag may get turned off in + * the code immediately below if the transform can be handled outside the + * row loop. + */ + if (gamma_correction) + png_ptr->transformations |= PNG_GAMMA; + + else + png_ptr->transformations &= ~PNG_GAMMA; } #endif -#if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED) - png_ptr->background_1 = png_ptr->background; + /* Certain transformations have the effect of preventing other + * transformations that happen afterward in png_do_read_transformations, + * resolve the interdependencies here. From the code of + * png_do_read_transformations the order is: + * + * 1) PNG_EXPAND (including PNG_EXPAND_tRNS) + * 2) PNG_STRIP_ALPHA (if no compose) + * 3) PNG_RGB_TO_GRAY + * 4) PNG_GRAY_TO_RGB iff !PNG_BACKGROUND_IS_GRAY + * 5) PNG_COMPOSE + * 6) PNG_GAMMA + * 7) PNG_STRIP_ALPHA (if compose) + * 8) PNG_ENCODE_ALPHA + * 9) PNG_SCALE_16_TO_8 + * 10) PNG_16_TO_8 + * 11) PNG_QUANTIZE (converts to palette) + * 12) PNG_EXPAND_16 + * 13) PNG_GRAY_TO_RGB iff PNG_BACKGROUND_IS_GRAY + * 14) PNG_INVERT_MONO + * 15) PNG_SHIFT + * 16) PNG_PACK + * 17) PNG_BGR + * 18) PNG_PACKSWAP + * 19) PNG_FILLER (includes PNG_ADD_ALPHA) + * 20) PNG_INVERT_ALPHA + * 21) PNG_SWAP_ALPHA + * 22) PNG_SWAP_BYTES + * 23) PNG_USER_TRANSFORM [must be last] + */ +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + if ((png_ptr->transformations & PNG_STRIP_ALPHA) && + !(png_ptr->transformations & PNG_COMPOSE)) + { + /* Stripping the alpha channel happens immediately after the 'expand' + * transformations, before all other transformation, so it cancels out + * the alpha handling. It has the side effect negating the effect of + * PNG_EXPAND_tRNS too: + */ + png_ptr->transformations &= ~(PNG_BACKGROUND_EXPAND | PNG_ENCODE_ALPHA | + PNG_EXPAND_tRNS); + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + + /* Kill the tRNS chunk itself too. Prior to 1.5.4 this did not happen + * so transparency information would remain just so long as it wasn't + * expanded. This produces unexpected API changes if the set of things + * that do PNG_EXPAND_tRNS changes (perfectly possible given the + * documentation - which says ask for what you want, accept what you + * get.) This makes the behavior consistent from 1.5.4: + */ + png_ptr->num_trans = 0; + } +#endif /* STRIP_ALPHA supported, no COMPOSE */ + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED + /* If the screen gamma is about 1.0 then the OPTIMIZE_ALPHA and ENCODE_ALPHA + * settings will have no effect. + */ + if (!png_gamma_significant(png_ptr->screen_gamma)) + { + png_ptr->transformations &= ~PNG_ENCODE_ALPHA; + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; + } #endif -#ifdef PNG_READ_GAMMA_SUPPORTED - if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0) - && png_gamma_threshold(png_ptr->screen_gamma, png_ptr->gamma)) +#if defined(PNG_READ_EXPAND_SUPPORTED) && \ + defined(PNG_READ_BACKGROUND_SUPPORTED) && \ + defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) + /* Detect gray background and attempt to enable optimization for + * gray --> RGB case. + * + * Note: if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or + * RGB_ALPHA (in which case need_expand is superfluous anyway), the + * background color might actually be gray yet not be flagged as such. + * This is not a problem for the current code, which uses + * PNG_BACKGROUND_IS_GRAY only to decide when to do the + * png_do_gray_to_rgb() transformation. + * + * TODO: this code needs to be revised to avoid the complexity and + * interdependencies. The color type of the background should be recorded in + * png_set_background, along with the bit depth, then the code has a record + * of exactly what color space the background is currently in. + */ + if (png_ptr->transformations & PNG_BACKGROUND_EXPAND) + { + /* PNG_BACKGROUND_EXPAND: the background is in the file color space, so if + * the file was greyscale the background value is gray. + */ + if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) + png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; + } + + else if (png_ptr->transformations & PNG_COMPOSE) { - int i, k; - k=0; - for (i=0; i<png_ptr->num_trans; i++) + /* PNG_COMPOSE: png_set_background was called with need_expand false, + * so the color is in the color space of the output or png_set_alpha_mode + * was called and the color is black. Ignore RGB_TO_GRAY because that + * happens before GRAY_TO_RGB. + */ + if (png_ptr->transformations & PNG_GRAY_TO_RGB) { - if (png_ptr->trans_alpha[i] != 0 && png_ptr->trans_alpha[i] != 0xff) - k=1; /* Partial transparency is present */ + if (png_ptr->background.red == png_ptr->background.green && + png_ptr->background.red == png_ptr->background.blue) + { + png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; + png_ptr->background.gray = png_ptr->background.red; + } } - if (k == 0) - png_ptr->transformations &= ~PNG_GAMMA; } +#endif /* PNG_READ_GRAY_TO_RGB_SUPPORTED (etc) */ + + /* For indexed PNG data (PNG_COLOR_TYPE_PALETTE) many of the transformations + * can be performed directly on the palette, and some (such as rgb to gray) + * can be optimized inside the palette. This is particularly true of the + * composite (background and alpha) stuff, which can be pretty much all done + * in the palette even if the result is expanded to RGB or gray afterward. + * + * NOTE: this is Not Yet Implemented, the code behaves as in 1.5.1 and + * earlier and the palette stuff is actually handled on the first row. This + * leads to the reported bug that the palette returned by png_get_PLTE is not + * updated. + */ + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + png_init_palette_transformations(png_ptr); + + else + png_init_rgb_transformations(png_ptr); + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ + defined(PNG_READ_EXPAND_16_SUPPORTED) + if ((png_ptr->transformations & PNG_EXPAND_16) && + (png_ptr->transformations & PNG_COMPOSE) && + !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + png_ptr->bit_depth != 16) + { + /* TODO: fix this. Because the expand_16 operation is after the compose + * handling the background color must be 8, not 16, bits deep, but the + * application will supply a 16-bit value so reduce it here. + * + * The PNG_BACKGROUND_EXPAND code above does not expand to 16 bits at + * present, so that case is ok (until do_expand_16 is moved.) + * + * NOTE: this discards the low 16 bits of the user supplied background + * color, but until expand_16 works properly there is no choice! + */ +# define CHOP(x) (x)=((png_uint_16)(((png_uint_32)(x)*255+32895) >> 16)) + CHOP(png_ptr->background.red); + CHOP(png_ptr->background.green); + CHOP(png_ptr->background.blue); + CHOP(png_ptr->background.gray); +# undef CHOP + } +#endif /* PNG_READ_BACKGROUND_SUPPORTED && PNG_READ_EXPAND_16_SUPPORTED */ + + /* NOTE: below 'PNG_READ_ALPHA_MODE_SUPPORTED' is presumed to also enable the + * background support (see the comments in scripts/pnglibconf.dfa), this + * allows pre-multiplication of the alpha channel to be implemented as + * compositing on black. This is probably sub-optimal and has been done in + * 1.5.4 betas simply to enable external critique and testing (i.e. to + * implement the new API quickly, without lots of internal changes.) + */ - if ((png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY)) && - png_ptr->gamma != 0) +#ifdef PNG_READ_GAMMA_SUPPORTED +# ifdef PNG_READ_BACKGROUND_SUPPORTED + /* Includes ALPHA_MODE */ + png_ptr->background_1 = png_ptr->background; +# endif + + /* This needs to change - in the palette image case a whole set of tables are + * built when it would be quicker to just calculate the correct value for + * each palette entry directly. Also, the test is too tricky - why check + * PNG_RGB_TO_GRAY if PNG_GAMMA is not set? The answer seems to be that + * PNG_GAMMA is cancelled even if the gamma is known? The test excludes the + * PNG_COMPOSE case, so apparently if there is no *overall* gamma correction + * the gamma tables will not be built even if composition is required on a + * gamma encoded value. + * + * In 1.5.4 this is addressed below by an additional check on the individual + * file gamma - if it is not 1.0 both RGB_TO_GRAY and COMPOSE need the + * tables. + */ + if ((png_ptr->transformations & PNG_GAMMA) + || ((png_ptr->transformations & PNG_RGB_TO_GRAY) + && (png_gamma_significant(png_ptr->gamma) || + png_gamma_significant(png_ptr->screen_gamma))) + || ((png_ptr->transformations & PNG_COMPOSE) + && (png_gamma_significant(png_ptr->gamma) + || png_gamma_significant(png_ptr->screen_gamma) +# ifdef PNG_READ_BACKGROUND_SUPPORTED + || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE + && png_gamma_significant(png_ptr->background_gamma)) +# endif + )) || ((png_ptr->transformations & PNG_ENCODE_ALPHA) + && png_gamma_significant(png_ptr->screen_gamma)) + ) { png_build_gamma_table(png_ptr, png_ptr->bit_depth); #ifdef PNG_READ_BACKGROUND_SUPPORTED - if (png_ptr->transformations & PNG_BACKGROUND) + if (png_ptr->transformations & PNG_COMPOSE) { - if (color_type == PNG_COLOR_TYPE_PALETTE) + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) { - /* Could skip if no transparency */ + /* We don't get to here unless there is a tRNS chunk with non-opaque + * entries - see the checking code at the start of this function. + */ png_color back, back_1; png_colorp palette = png_ptr->palette; int num_palette = png_ptr->num_palette; @@ -1013,26 +1566,39 @@ png_init_read_transformations(png_structp png_ptr) if (png_gamma_significant(gs)) { + back.red = png_gamma_8bit_correct(png_ptr->background.red, + gs); + back.green = png_gamma_8bit_correct(png_ptr->background.green, + gs); + back.blue = png_gamma_8bit_correct(png_ptr->background.blue, + gs); + } + + else + { back.red = (png_byte)png_ptr->background.red; back.green = (png_byte)png_ptr->background.green; back.blue = (png_byte)png_ptr->background.blue; } + if (png_gamma_significant(g)) + { + back_1.red = png_gamma_8bit_correct(png_ptr->background.red, + g); + back_1.green = png_gamma_8bit_correct( + png_ptr->background.green, g); + back_1.blue = png_gamma_8bit_correct(png_ptr->background.blue, + g); + } + else { - back.red = png_gamma_8bit_correct(png_ptr->background.red, - gs); - back.green = png_gamma_8bit_correct(png_ptr->background.green, - gs); - back.blue = png_gamma_8bit_correct(png_ptr->background.blue, - gs); + back_1.red = (png_byte)png_ptr->background.red; + back_1.green = (png_byte)png_ptr->background.green; + back_1.blue = (png_byte)png_ptr->background.blue; } - back_1.red = png_gamma_8bit_correct(png_ptr->background.red, g); - back_1.green = png_gamma_8bit_correct(png_ptr->background.green, - g); - back_1.blue = png_gamma_8bit_correct(png_ptr->background.blue, - g); } + for (i = 0; i < num_palette; i++) { if (i < (int)png_ptr->num_trans && @@ -1066,19 +1632,18 @@ png_init_read_transformations(png_structp png_ptr) palette[i].blue = png_ptr->gamma_table[palette[i].blue]; } } - /* Prevent the transformations being done again, and make sure - * that the now spurious alpha channel is stripped - the code - * has just reduced background composition and gamma correction - * to a simple alpha channel strip. + + /* Prevent the transformations being done again. + * + * NOTE: this is highly dubious; it zaps the transformations in + * place. This seems inconsistent with the general treatment of the + * transformations elsewhere. */ - png_ptr->transformations &= ~PNG_BACKGROUND; - png_ptr->transformations &= ~PNG_GAMMA; - png_ptr->flags |= PNG_FLAG_STRIP_ALPHA; - } + png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA); + } /* color_type == PNG_COLOR_TYPE_PALETTE */ /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */ - else - /* color_type != PNG_COLOR_TYPE_PALETTE */ + else /* color_type != PNG_COLOR_TYPE_PALETTE */ { png_fixed_point g = PNG_FP_1; png_fixed_point gs = PNG_FP_1; @@ -1144,17 +1709,21 @@ png_init_read_transformations(png_structp png_ptr) png_ptr->background.red = png_ptr->background.green = png_ptr->background.blue = png_ptr->background.gray; } - } - } + } /* color_type != PNG_COLOR_TYPE_PALETTE */ + }/* png_ptr->transformations & PNG_BACKGROUND */ + else /* Transformation does not include PNG_BACKGROUND */ #endif /* PNG_READ_BACKGROUND_SUPPORTED */ - if (color_type == PNG_COLOR_TYPE_PALETTE) + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) { png_colorp palette = png_ptr->palette; int num_palette = png_ptr->num_palette; int i; + /*NOTE: there are other transformations that should probably be in here + * too. + */ for (i = 0; i < num_palette; i++) { palette[i].red = png_ptr->gamma_table[palette[i].red]; @@ -1164,16 +1733,17 @@ png_init_read_transformations(png_structp png_ptr) /* Done the gamma correction. */ png_ptr->transformations &= ~PNG_GAMMA; - } + } /* color_type == PALETTE && !PNG_BACKGROUND transformation */ } #ifdef PNG_READ_BACKGROUND_SUPPORTED else #endif #endif /* PNG_READ_GAMMA_SUPPORTED */ + #ifdef PNG_READ_BACKGROUND_SUPPORTED - /* No GAMMA transformation */ - if ((png_ptr->transformations & PNG_BACKGROUND) && - (color_type == PNG_COLOR_TYPE_PALETTE)) + /* No GAMMA transformation (see the hanging else 4 lines above) */ + if ((png_ptr->transformations & PNG_COMPOSE) && + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)) { int i; int istop = (int)png_ptr->num_trans; @@ -1205,15 +1775,13 @@ png_init_read_transformations(png_structp png_ptr) } } - /* Handled alpha, still need to strip the channel. */ - png_ptr->transformations &= ~PNG_BACKGROUND; - png_ptr->flags |= PNG_FLAG_STRIP_ALPHA; + png_ptr->transformations &= ~PNG_COMPOSE; } #endif /* PNG_READ_BACKGROUND_SUPPORTED */ #ifdef PNG_READ_SHIFT_SUPPORTED if ((png_ptr->transformations & PNG_SHIFT) && - (color_type == PNG_COLOR_TYPE_PALETTE)) + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)) { png_uint_16 i; png_uint_16 istop = png_ptr->num_palette; @@ -1238,12 +1806,6 @@ png_init_read_transformations(png_structp png_ptr) } } #endif /* PNG_READ_SHIFT_SUPPORTED */ - } -#if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \ - && !defined(PNG_READ_BACKGROUND_SUPPORTED) - if (png_ptr) - return; -#endif } /* Modify the info structure to reflect the transformations. The @@ -1260,8 +1822,11 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr) { if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) { - if (png_ptr->num_trans && - (png_ptr->transformations & PNG_EXPAND_tRNS)) + /* This check must match what actually happens in + * png_do_expand_palette; if it ever checks the tRNS chunk to see if + * it is all opaque we must do the same (at present it does not.) + */ + if (png_ptr->num_trans > 0) info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA; else @@ -1285,36 +1850,61 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr) } #endif -#ifdef PNG_READ_BACKGROUND_SUPPORTED - if (png_ptr->transformations & PNG_BACKGROUND) - { - info_ptr->color_type = (png_byte)(info_ptr->color_type & - ~PNG_COLOR_MASK_ALPHA); - info_ptr->num_trans = 0; +#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) + /* The following is almost certainly wrong unless the background value is in + * the screen space! + */ + if (png_ptr->transformations & PNG_COMPOSE) info_ptr->background = png_ptr->background; - } #endif #ifdef PNG_READ_GAMMA_SUPPORTED - if (png_ptr->transformations & PNG_GAMMA) - { - info_ptr->gamma = png_ptr->gamma; - } + /* The following used to be conditional on PNG_GAMMA (prior to 1.5.4), + * however it seems that the code in png_init_read_transformations, which has + * been called before this from png_read_update_info->png_read_start_row + * sometimes does the gamma transform and cancels the flag. + */ + info_ptr->gamma = png_ptr->gamma; #endif -#ifdef PNG_READ_16_TO_8_SUPPORTED -#ifdef PNG_READ_16BIT_SUPPORTED - if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16)) - info_ptr->bit_depth = 8; -#else - /* Force chopping 16-bit input down to 8 */ if (info_ptr->bit_depth == 16) { - png_ptr->transformations |=PNG_16_TO_8; - info_ptr->bit_depth = 8; +# ifdef PNG_READ_16BIT_SUPPORTED +# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED + if (png_ptr->transformations & PNG_SCALE_16_TO_8) + info_ptr->bit_depth = 8; +# endif + +# ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED + if (png_ptr->transformations & PNG_16_TO_8) + info_ptr->bit_depth = 8; +# endif + +# else + /* No 16 bit support: force chopping 16-bit input down to 8, in this case + * the app program can chose if both APIs are available by setting the + * correct scaling to use. + */ +# ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED + /* For compatibility with previous versions use the strip method by + * default. This code works because if PNG_SCALE_16_TO_8 is already + * set the code below will do that in preference to the chop. + */ + png_ptr->transformations |= PNG_16_TO_8; + info_ptr->bit_depth = 8; +# else + +# if PNG_READ_SCALE_16_TO_8_SUPPORTED + png_ptr->transformations |= PNG_SCALE_16_TO_8; + info_ptr->bit_depth = 8; +# else + + CONFIGURATION ERROR: you must enable at least one 16 to 8 method +# endif +# endif +#endif /* !READ_16BIT_SUPPORTED */ } -#endif -#endif #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED if (png_ptr->transformations & PNG_GRAY_TO_RGB) @@ -1338,6 +1928,14 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr) } #endif +#ifdef PNG_READ_EXPAND_16_SUPPORTED + if (png_ptr->transformations & PNG_EXPAND_16 && info_ptr->bit_depth == 8 && + info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) + { + info_ptr->bit_depth = 16; + } +#endif + #ifdef PNG_READ_PACK_SUPPORTED if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8)) info_ptr->bit_depth = 8; @@ -1353,8 +1951,11 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr) info_ptr->channels = 1; #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED - if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA) + if (png_ptr->transformations & PNG_STRIP_ALPHA) + { info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA; + info_ptr->num_trans = 0; + } #endif if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) @@ -1390,6 +1991,14 @@ defined(PNG_READ_USER_TRANSFORM_SUPPORTED) info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width); + /* Adding in 1.5.4: cache the above value in png_struct so that we can later + * check in png_rowbytes that the user buffer won't get overwritten. Note + * that the field is not always set - if png_read_update_info isn't called + * the application has to either not do any transforms or get the calculation + * right itself. + */ + png_ptr->info_rowbytes = info_ptr->rowbytes; + #ifndef PNG_READ_EXPAND_SUPPORTED if (png_ptr) return; @@ -1407,29 +2016,27 @@ png_do_read_transformations(png_structp png_ptr) if (png_ptr->row_buf == NULL) { -#ifdef PNG_CONSOLE_IO_SUPPORTED - char msg[50]; - - png_snprintf2(msg, 50, - "NULL row buffer for row %ld, pass %d", (long)png_ptr->row_number, - png_ptr->pass); - png_error(png_ptr, msg); -#else + /* Prior to 1.5.4 this output row/pass where the NULL pointer is, but this + * error is incredibly rare and incredibly easy to debug without this + * information. + */ png_error(png_ptr, "NULL row buffer"); -#endif } -#ifdef PNG_WARN_UNINITIALIZED_ROW - if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) - /* Application has failed to call either png_read_start_image() - * or png_read_update_info() after setting transforms that expand - * pixels. This check added to libpng-1.2.19 + + /* The following is debugging; prior to 1.5.4 the code was never compiled in; + * in 1.5.4 PNG_FLAG_DETECT_UNINITIALIZED was added and the macro + * PNG_WARN_UNINITIALIZED_ROW removed. In 1.5 the new flag is set only for + * selected new APIs to ensure that there is no API change. + */ + if ((png_ptr->flags & PNG_FLAG_DETECT_UNINITIALIZED) != 0 && + !(png_ptr->flags & PNG_FLAG_ROW_INIT)) + { + /* Application has failed to call either png_read_start_image() or + * png_read_update_info() after setting transforms that expand pixels. + * This check added to libpng-1.2.19 (but not enabled until 1.5.4). */ -#if (PNG_WARN_UNINITIALIZED_ROW==1) png_error(png_ptr, "Uninitialized row"); -#else - png_warning(png_ptr, "Uninitialized row"); -#endif -#endif + } #ifdef PNG_READ_EXPAND_SUPPORTED if (png_ptr->transformations & PNG_EXPAND) @@ -1439,14 +2046,15 @@ png_do_read_transformations(png_structp png_ptr) png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1, png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans); } + else { if (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND_tRNS)) png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, &(png_ptr->trans_color)); - else + else png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, NULL); } @@ -1454,9 +2062,12 @@ png_do_read_transformations(png_structp png_ptr) #endif #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED - if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA) - png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, - PNG_FLAG_FILLER_AFTER | (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)); + if ((png_ptr->transformations & PNG_STRIP_ALPHA) && + !(png_ptr->transformations & PNG_COMPOSE) && + (png_ptr->row_info.color_type == PNG_COLOR_TYPE_RGB_ALPHA || + png_ptr->row_info.color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) + png_do_strip_channel(&(png_ptr->row_info), png_ptr->row_buf + 1, + 0 /* at_start == false, because SWAP_ALPHA happens later */); #endif #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED @@ -1520,36 +2131,49 @@ png_do_read_transformations(png_structp png_ptr) png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); #endif -#ifdef PNG_READ_BACKGROUND_SUPPORTED - if ((png_ptr->transformations & PNG_BACKGROUND) && - ((png_ptr->num_trans != 0) || - (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) - png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1, - &(png_ptr->trans_color), &(png_ptr->background) -#ifdef PNG_READ_GAMMA_SUPPORTED - , &(png_ptr->background_1), - png_ptr->gamma_table, png_ptr->gamma_from_1, - png_ptr->gamma_to_1, png_ptr->gamma_16_table, - png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1, - png_ptr->gamma_shift -#endif - ); +#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\ + (defined PNG_READ_ALPHA_MODE_SUPPORTED) + if (png_ptr->transformations & PNG_COMPOSE) + png_do_compose(&(png_ptr->row_info), png_ptr->row_buf + 1, png_ptr); #endif #ifdef PNG_READ_GAMMA_SUPPORTED if ((png_ptr->transformations & PNG_GAMMA) && -#ifdef PNG_READ_BACKGROUND_SUPPORTED - !((png_ptr->transformations & PNG_BACKGROUND) && +#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\ + (defined PNG_READ_ALPHA_MODE_SUPPORTED) + !((png_ptr->transformations & PNG_COMPOSE) && ((png_ptr->num_trans != 0) || (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) && #endif (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)) - png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1, - png_ptr->gamma_table, png_ptr->gamma_16_table, - png_ptr->gamma_shift); + png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1, png_ptr); +#endif + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + if ((png_ptr->transformations & PNG_STRIP_ALPHA) && + (png_ptr->transformations & PNG_COMPOSE) && + (png_ptr->row_info.color_type == PNG_COLOR_TYPE_RGB_ALPHA || + png_ptr->row_info.color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) + png_do_strip_channel(&(png_ptr->row_info), png_ptr->row_buf + 1, + 0 /* at_start == false, because SWAP_ALPHA happens later */); +#endif + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED + if ((png_ptr->transformations & PNG_ENCODE_ALPHA) && + (png_ptr->row_info.color_type & PNG_COLOR_MASK_ALPHA)) + png_do_encode_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1, png_ptr); +#endif + +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED + if (png_ptr->transformations & PNG_SCALE_16_TO_8) + png_do_scale_16_to_8(&(png_ptr->row_info), png_ptr->row_buf + 1); #endif -#ifdef PNG_READ_16_TO_8_SUPPORTED +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED + /* There is no harm in doing both of these because only one has any effect, + * by putting the 'scale' option first if the app asks for scale (either by + * calling the API or in a TRANSFORM flag) this is what happens. + */ if (png_ptr->transformations & PNG_16_TO_8) png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1); #endif @@ -1565,6 +2189,23 @@ png_do_read_transformations(png_structp png_ptr) } #endif /* PNG_READ_QUANTIZE_SUPPORTED */ +#ifdef PNG_READ_EXPAND_16_SUPPORTED + /* Do the expansion now, after all the arithmetic has been done. Notice + * that previous transformations can handle the PNG_EXPAND_16 flag if this + * is efficient (particularly true in the case of gamma correction, where + * better accuracy results faster!) + */ + if (png_ptr->transformations & PNG_EXPAND_16) + png_do_expand_16(&png_ptr->row_info, png_ptr->row_buf + 1); +#endif + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + /*NOTE: moved here in 1.5.4 (from much later in this list.) */ + if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && + (png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) + png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); +#endif + #ifdef PNG_READ_INVERT_SUPPORTED if (png_ptr->transformations & PNG_INVERT_MONO) png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); @@ -1591,13 +2232,6 @@ png_do_read_transformations(png_structp png_ptr) png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1); #endif -#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED - /* If gray -> RGB, do so now only if we did not do so above */ - if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && - (png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) - png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1); -#endif - #ifdef PNG_READ_FILLER_SUPPORTED if (png_ptr->transformations & PNG_FILLER) png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, @@ -1649,7 +2283,6 @@ png_do_read_transformations(png_structp png_ptr) png_ptr->row_info.width); } #endif - } #ifdef PNG_READ_PACK_SUPPORTED @@ -1804,7 +2437,7 @@ png_do_unshift(png_row_infop row_info, png_bytep row, switch (row_info->bit_depth) { default: - break; + break; case 2: { @@ -1871,54 +2504,86 @@ png_do_unshift(png_row_infop row_info, png_bytep row, } #endif -#ifdef PNG_READ_16_TO_8_SUPPORTED -/* Chop rows of bit depth 16 down to 8 */ +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED +/* Scale rows of bit depth 16 down to 8 accurately */ void /* PRIVATE */ -png_do_chop(png_row_infop row_info, png_bytep row) +png_do_scale_16_to_8(png_row_infop row_info, png_bytep row) { - png_debug(1, "in png_do_chop"); + png_debug(1, "in png_do_scale_16_to_8"); if (row_info->bit_depth == 16) { - png_bytep sp = row; - png_bytep dp = row; - png_uint_32 i; - png_uint_32 istop = row_info->width * row_info->channels; + png_bytep sp = row; /* source */ + png_bytep dp = row; /* destinaton */ + png_bytep ep = sp + row_info->rowbytes; /* end+1 */ - for (i = 0; i<istop; i++, sp += 2, dp++) + while (sp < ep) { -#ifdef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED - /* This does a more accurate scaling of the 16-bit color - * value, rather than a simple low-byte truncation. - * - * What the ideal calculation should be: - * *dp = (((((png_uint_32)(*sp) << 8) | - * (png_uint_32)(*(sp + 1))) * 255 + 127) - * / (png_uint_32)65535L; - * - * GRR: no, I think this is what it really should be: - * *dp = (((((png_uint_32)(*sp) << 8) | - * (png_uint_32)(*(sp + 1))) + 128L) - * / (png_uint_32)257L; - * - * GRR: here's the exact calculation with shifts: - * temp = (((png_uint_32)(*sp) << 8) | - * (png_uint_32)(*(sp + 1))) + 128L; - * *dp = (temp - (temp >> 8)) >> 8; - * - * Approximate calculation with shift/add instead of multiply/divide: - * *dp = ((((png_uint_32)(*sp) << 8) | - * (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8; - * - * What we actually do to avoid extra shifting and conversion: - */ + /* The input is an array of 16 bit components, these must be scaled to + * 8 bits each. For a 16 bit value V the required value (from the PNG + * specification) is: + * + * (V * 255) / 65535 + * + * This reduces to round(V / 257), or floor((V + 128.5)/257) + * + * Represent V as the two byte value vhi.vlo. Make a guess that the + * result is the top byte of V, vhi, then the correction to this value + * is: + * + * error = floor(((V-vhi.vhi) + 128.5) / 257) + * = floor(((vlo-vhi) + 128.5) / 257) + * + * This can be approximated using integer arithmetic (and a signed + * shift): + * + * error = (vlo-vhi+128) >> 8; + * + * The approximate differs from the exact answer only when (vlo-vhi) is + * 128; it then gives a correction of +1 when the exact correction is + * 0. This gives 128 errors. The exact answer (correct for all 16 bit + * input values) is: + * + * error = (vlo-vhi+128)*65535 >> 24; + * + * An alternative arithmetic calculation which also gives no errors is: + * + * (V * 255 + 32895) >> 16 + */ - *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0); -#else - /* Simply discard the low order byte */ - *dp = *sp; + png_int_32 tmp = *sp++; /* must be signed! */ + tmp += (((int)*sp++ - tmp + 128) * 65535) >> 24; + *dp++ = (png_byte)tmp; + } + + row_info->bit_depth = 8; + row_info->pixel_depth = (png_byte)(8 * row_info->channels); + row_info->rowbytes = row_info->width * row_info->channels; + } +} #endif + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED +void /* PRIVATE */ +/* Simply discard the low byte. This was the default behavior prior + * to libpng-1.5.4. + */ +png_do_chop(png_row_infop row_info, png_bytep row) +{ + png_debug(1, "in png_do_chop"); + + if (row_info->bit_depth == 16) + { + png_bytep sp = row; /* source */ + png_bytep dp = row; /* destinaton */ + png_bytep ep = sp + row_info->rowbytes; /* end+1 */ + + while (sp < ep) + { + *dp++ = *sp; + sp += 2; /* skip low byte */ } + row_info->bit_depth = 8; row_info->pixel_depth = (png_byte)(8 * row_info->channels); row_info->rowbytes = row_info->width * row_info->channels; @@ -2673,11 +3338,13 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row) return rgb_error; } #endif +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ +#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED /* Build a grayscale palette. Palette is assumed to be 1 << bit_depth * large of png_color. This lets grayscale images be treated as * paletted. Most useful for gamma correction and simplification - * of code. + * of code. This API is not used internally. */ void PNGAPI png_build_grayscale_palette(int bit_depth, png_colorp palette) @@ -2727,34 +3394,36 @@ png_build_grayscale_palette(int bit_depth, png_colorp palette) palette[i].blue = (png_byte)v; } } +#endif +#ifdef PNG_READ_TRANSFORMS_SUPPORTED #ifdef PNG_READ_BACKGROUND_SUPPORTED /* Replace any alpha or transparency with the supplied background color. * "background" is already in the screen gamma, while "background_1" is * at a gamma of 1.0. Paletted files have already been taken care of. */ void /* PRIVATE */ -png_do_background(png_row_infop row_info, png_bytep row, - png_const_color_16p trans_color, png_const_color_16p background +png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr) +{ #ifdef PNG_READ_GAMMA_SUPPORTED - , png_const_color_16p background_1, png_const_bytep gamma_table, - png_const_bytep gamma_from_1, png_const_bytep gamma_to_1, - png_const_uint_16pp gamma_16, png_const_uint_16pp gamma_16_from_1, - png_const_uint_16pp gamma_16_to_1, int gamma_shift + png_const_bytep gamma_table = png_ptr->gamma_table; + png_const_bytep gamma_from_1 = png_ptr->gamma_from_1; + png_const_bytep gamma_to_1 = png_ptr->gamma_to_1; + png_const_uint_16pp gamma_16 = png_ptr->gamma_16_table; + png_const_uint_16pp gamma_16_from_1 = png_ptr->gamma_16_from_1; + png_const_uint_16pp gamma_16_to_1 = png_ptr->gamma_16_to_1; + int gamma_shift = png_ptr->gamma_shift; #endif - ) -{ - png_bytep sp, dp; + + png_bytep sp; png_uint_32 i; png_uint_32 row_width = row_info->width; + int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0; int shift; - png_debug(1, "in png_do_background"); + png_debug(1, "in png_do_compose"); - if (background != NULL && - (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) || - (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_color))) { switch (row_info->color_type) { @@ -2769,10 +3438,10 @@ png_do_background(png_row_infop row_info, png_bytep row, for (i = 0; i < row_width; i++) { if ((png_uint_16)((*sp >> shift) & 0x01) - == trans_color->gray) + == png_ptr->trans_color.gray) { *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff); - *sp |= (png_byte)(background->gray << shift); + *sp |= (png_byte)(png_ptr->background.gray << shift); } if (!shift) @@ -2797,10 +3466,10 @@ png_do_background(png_row_infop row_info, png_bytep row, for (i = 0; i < row_width; i++) { if ((png_uint_16)((*sp >> shift) & 0x03) - == trans_color->gray) + == png_ptr->trans_color.gray) { *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); - *sp |= (png_byte)(background->gray << shift); + *sp |= (png_byte)(png_ptr->background.gray << shift); } else @@ -2831,10 +3500,10 @@ png_do_background(png_row_infop row_info, png_bytep row, for (i = 0; i < row_width; i++) { if ((png_uint_16)((*sp >> shift) & 0x03) - == trans_color->gray) + == png_ptr->trans_color.gray) { *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff); - *sp |= (png_byte)(background->gray << shift); + *sp |= (png_byte)(png_ptr->background.gray << shift); } if (!shift) @@ -2860,10 +3529,10 @@ png_do_background(png_row_infop row_info, png_bytep row, for (i = 0; i < row_width; i++) { if ((png_uint_16)((*sp >> shift) & 0x0f) - == trans_color->gray) + == png_ptr->trans_color.gray) { *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); - *sp |= (png_byte)(background->gray << shift); + *sp |= (png_byte)(png_ptr->background.gray << shift); } else @@ -2894,10 +3563,10 @@ png_do_background(png_row_infop row_info, png_bytep row, for (i = 0; i < row_width; i++) { if ((png_uint_16)((*sp >> shift) & 0x0f) - == trans_color->gray) + == png_ptr->trans_color.gray) { *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff); - *sp |= (png_byte)(background->gray << shift); + *sp |= (png_byte)(png_ptr->background.gray << shift); } if (!shift) @@ -2921,8 +3590,8 @@ png_do_background(png_row_infop row_info, png_bytep row, sp = row; for (i = 0; i < row_width; i++, sp++) { - if (*sp == trans_color->gray) - *sp = (png_byte)background->gray; + if (*sp == png_ptr->trans_color.gray) + *sp = (png_byte)png_ptr->background.gray; else *sp = gamma_table[*sp]; @@ -2934,8 +3603,8 @@ png_do_background(png_row_infop row_info, png_bytep row, sp = row; for (i = 0; i < row_width; i++, sp++) { - if (*sp == trans_color->gray) - *sp = (png_byte)background->gray; + if (*sp == png_ptr->trans_color.gray) + *sp = (png_byte)png_ptr->background.gray; } } break; @@ -2953,11 +3622,11 @@ png_do_background(png_row_infop row_info, png_bytep row, v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - if (v == trans_color->gray) + if (v == png_ptr->trans_color.gray) { /* Background is already in screen gamma */ - *sp = (png_byte)((background->gray >> 8) & 0xff); - *(sp + 1) = (png_byte)(background->gray & 0xff); + *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); } else @@ -2978,10 +3647,10 @@ png_do_background(png_row_infop row_info, png_bytep row, v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - if (v == trans_color->gray) + if (v == png_ptr->trans_color.gray) { - *sp = (png_byte)((background->gray >> 8) & 0xff); - *(sp + 1) = (png_byte)(background->gray & 0xff); + *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); } } } @@ -3004,13 +3673,13 @@ png_do_background(png_row_infop row_info, png_bytep row, sp = row; for (i = 0; i < row_width; i++, sp += 3) { - if (*sp == trans_color->red && - *(sp + 1) == trans_color->green && - *(sp + 2) == trans_color->blue) + if (*sp == png_ptr->trans_color.red && + *(sp + 1) == png_ptr->trans_color.green && + *(sp + 2) == png_ptr->trans_color.blue) { - *sp = (png_byte)background->red; - *(sp + 1) = (png_byte)background->green; - *(sp + 2) = (png_byte)background->blue; + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; } else @@ -3027,13 +3696,13 @@ png_do_background(png_row_infop row_info, png_bytep row, sp = row; for (i = 0; i < row_width; i++, sp += 3) { - if (*sp == trans_color->red && - *(sp + 1) == trans_color->green && - *(sp + 2) == trans_color->blue) + if (*sp == png_ptr->trans_color.red && + *(sp + 1) == png_ptr->trans_color.green && + *(sp + 2) == png_ptr->trans_color.blue) { - *sp = (png_byte)background->red; - *(sp + 1) = (png_byte)background->green; - *(sp + 2) = (png_byte)background->blue; + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; } } } @@ -3054,16 +3723,17 @@ png_do_background(png_row_infop row_info, png_bytep row, png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + *(sp + 5)); - if (r == trans_color->red && g == trans_color->green && - b == trans_color->blue) + if (r == png_ptr->trans_color.red && + g == png_ptr->trans_color.green && + b == png_ptr->trans_color.blue) { /* Background is already in screen gamma */ - *sp = (png_byte)((background->red >> 8) & 0xff); - *(sp + 1) = (png_byte)(background->red & 0xff); - *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); - *(sp + 3) = (png_byte)(background->green & 0xff); - *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); - *(sp + 5) = (png_byte)(background->blue & 0xff); + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); } else @@ -3097,15 +3767,16 @@ png_do_background(png_row_infop row_info, png_bytep row, png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + *(sp + 5)); - if (r == trans_color->red && g == trans_color->green && - b == trans_color->blue) + if (r == png_ptr->trans_color.red && + g == png_ptr->trans_color.green && + b == png_ptr->trans_color.blue) { - *sp = (png_byte)((background->red >> 8) & 0xff); - *(sp + 1) = (png_byte)(background->red & 0xff); - *(sp + 2) = (png_byte)((background->green >> 8) & 0xff); - *(sp + 3) = (png_byte)(background->green & 0xff); - *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff); - *(sp + 5) = (png_byte)(background->blue & 0xff); + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); } } } @@ -3122,18 +3793,17 @@ png_do_background(png_row_infop row_info, png_bytep row, gamma_table != NULL) { sp = row; - dp = row; - for (i = 0; i < row_width; i++, sp += 2, dp++) + for (i = 0; i < row_width; i++, sp += 2) { png_uint_16 a = *(sp + 1); if (a == 0xff) - *dp = gamma_table[*sp]; + *sp = gamma_table[*sp]; else if (a == 0) { /* Background is already in screen gamma */ - *dp = (png_byte)background->gray; + *sp = (png_byte)png_ptr->background.gray; } else @@ -3141,8 +3811,10 @@ png_do_background(png_row_infop row_info, png_bytep row, png_byte v, w; v = gamma_to_1[*sp]; - png_composite(w, v, a, background_1->gray); - *dp = gamma_from_1[w]; + png_composite(w, v, a, png_ptr->background_1.gray); + if (!optimize) + w = gamma_from_1[w]; + *sp = w; } } } @@ -3150,24 +3822,15 @@ png_do_background(png_row_infop row_info, png_bytep row, #endif { sp = row; - dp = row; - for (i = 0; i < row_width; i++, sp += 2, dp++) + for (i = 0; i < row_width; i++, sp += 2) { png_byte a = *(sp + 1); - if (a == 0xff) - *dp = *sp; - -#ifdef PNG_READ_GAMMA_SUPPORTED - else if (a == 0) - *dp = (png_byte)background->gray; - - else - png_composite(*dp, *sp, a, background_1->gray); + if (a == 0) + *sp = (png_byte)png_ptr->background.gray; -#else - *dp = (png_byte)background->gray; -#endif + else if (a < 0xff) + png_composite(*sp, *sp, a, png_ptr->background_1.gray); } } } @@ -3178,8 +3841,7 @@ png_do_background(png_row_infop row_info, png_bytep row, gamma_16_to_1 != NULL) { sp = row; - dp = row; - for (i = 0; i < row_width; i++, sp += 4, dp += 2) + for (i = 0; i < row_width; i++, sp += 4) { png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) + *(sp + 3)); @@ -3189,69 +3851,56 @@ png_do_background(png_row_infop row_info, png_bytep row, png_uint_16 v; v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *dp = (png_byte)((v >> 8) & 0xff); - *(dp + 1) = (png_byte)(v & 0xff); + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); } -#ifdef PNG_READ_GAMMA_SUPPORTED else if (a == 0) -#else - else -#endif { /* Background is already in screen gamma */ - *dp = (png_byte)((background->gray >> 8) & 0xff); - *(dp + 1) = (png_byte)(background->gray & 0xff); + *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); } -#ifdef PNG_READ_GAMMA_SUPPORTED else { png_uint_16 g, v, w; g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; - png_composite_16(v, g, a, background_1->gray); - w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8]; - *dp = (png_byte)((w >> 8) & 0xff); - *(dp + 1) = (png_byte)(w & 0xff); + png_composite_16(v, g, a, png_ptr->background_1.gray); + if (optimize) + w = v; + else + w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8]; + *sp = (png_byte)((w >> 8) & 0xff); + *(sp + 1) = (png_byte)(w & 0xff); } -#endif } } else #endif { sp = row; - dp = row; - for (i = 0; i < row_width; i++, sp += 4, dp += 2) + for (i = 0; i < row_width; i++, sp += 4) { png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) + *(sp + 3)); - if (a == (png_uint_16)0xffff) - png_memcpy(dp, sp, 2); - -#ifdef PNG_READ_GAMMA_SUPPORTED - else if (a == 0) -#else - else -#endif + if (a == 0) { - *dp = (png_byte)((background->gray >> 8) & 0xff); - *(dp + 1) = (png_byte)(background->gray & 0xff); + *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); } -#ifdef PNG_READ_GAMMA_SUPPORTED - else + else if (a < 0xffff) { png_uint_16 g, v; g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - png_composite_16(v, g, a, background_1->gray); - *dp = (png_byte)((v >> 8) & 0xff); - *(dp + 1) = (png_byte)(v & 0xff); + png_composite_16(v, g, a, png_ptr->background_1.gray); + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); } -#endif } } } @@ -3267,24 +3916,23 @@ png_do_background(png_row_infop row_info, png_bytep row, gamma_table != NULL) { sp = row; - dp = row; - for (i = 0; i < row_width; i++, sp += 4, dp += 3) + for (i = 0; i < row_width; i++, sp += 4) { png_byte a = *(sp + 3); if (a == 0xff) { - *dp = gamma_table[*sp]; - *(dp + 1) = gamma_table[*(sp + 1)]; - *(dp + 2) = gamma_table[*(sp + 2)]; + *sp = gamma_table[*sp]; + *(sp + 1) = gamma_table[*(sp + 1)]; + *(sp + 2) = gamma_table[*(sp + 2)]; } else if (a == 0) { /* Background is already in screen gamma */ - *dp = (png_byte)background->red; - *(dp + 1) = (png_byte)background->green; - *(dp + 2) = (png_byte)background->blue; + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; } else @@ -3292,16 +3940,19 @@ png_do_background(png_row_infop row_info, png_bytep row, png_byte v, w; v = gamma_to_1[*sp]; - png_composite(w, v, a, background_1->red); - *dp = gamma_from_1[w]; + png_composite(w, v, a, png_ptr->background_1.red); + if (!optimize) w = gamma_from_1[w]; + *sp = w; v = gamma_to_1[*(sp + 1)]; - png_composite(w, v, a, background_1->green); - *(dp + 1) = gamma_from_1[w]; + png_composite(w, v, a, png_ptr->background_1.green); + if (!optimize) w = gamma_from_1[w]; + *(sp + 1) = w; v = gamma_to_1[*(sp + 2)]; - png_composite(w, v, a, background_1->blue); - *(dp + 2) = gamma_from_1[w]; + png_composite(w, v, a, png_ptr->background_1.blue); + if (!optimize) w = gamma_from_1[w]; + *(sp + 2) = w; } } } @@ -3309,34 +3960,26 @@ png_do_background(png_row_infop row_info, png_bytep row, #endif { sp = row; - dp = row; - for (i = 0; i < row_width; i++, sp += 4, dp += 3) + for (i = 0; i < row_width; i++, sp += 4) { png_byte a = *(sp + 3); - if (a == 0xff) + if (a == 0) { - *dp = *sp; - *(dp + 1) = *(sp + 1); - *(dp + 2) = *(sp + 2); + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; } - else if (a == 0) - { - *dp = (png_byte)background->red; - *(dp + 1) = (png_byte)background->green; - *(dp + 2) = (png_byte)background->blue; - } - - else + else if (a < 0xff) { - png_composite(*dp, *sp, a, background->red); + png_composite(*sp, *sp, a, png_ptr->background.red); - png_composite(*(dp + 1), *(sp + 1), a, - background->green); + png_composite(*(sp + 1), *(sp + 1), a, + png_ptr->background.green); - png_composite(*(dp + 2), *(sp + 2), a, - background->blue); + png_composite(*(sp + 2), *(sp + 2), a, + png_ptr->background.blue); } } } @@ -3348,8 +3991,7 @@ png_do_background(png_row_infop row_info, png_bytep row, gamma_16_to_1 != NULL) { sp = row; - dp = row; - for (i = 0; i < row_width; i++, sp += 8, dp += 6) + for (i = 0; i < row_width; i++, sp += 8) { png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) << 8) + (png_uint_16)(*(sp + 7))); @@ -3359,53 +4001,55 @@ png_do_background(png_row_infop row_info, png_bytep row, png_uint_16 v; v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *dp = (png_byte)((v >> 8) & 0xff); - *(dp + 1) = (png_byte)(v & 0xff); + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; - *(dp + 2) = (png_byte)((v >> 8) & 0xff); - *(dp + 3) = (png_byte)(v & 0xff); + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; - *(dp + 4) = (png_byte)((v >> 8) & 0xff); - *(dp + 5) = (png_byte)(v & 0xff); + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); } else if (a == 0) { /* Background is already in screen gamma */ - *dp = (png_byte)((background->red >> 8) & 0xff); - *(dp + 1) = (png_byte)(background->red & 0xff); - *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); - *(dp + 3) = (png_byte)(background->green & 0xff); - *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); - *(dp + 5) = (png_byte)(background->blue & 0xff); + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); } else { - png_uint_16 v, w, x; + png_uint_16 v, w; v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; - png_composite_16(w, v, a, background_1->red); - - x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; - *dp = (png_byte)((x >> 8) & 0xff); - *(dp + 1) = (png_byte)(x & 0xff); + png_composite_16(w, v, a, png_ptr->background_1.red); + if (!optimize) + w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; + *sp = (png_byte)((w >> 8) & 0xff); + *(sp + 1) = (png_byte)(w & 0xff); v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; - png_composite_16(w, v, a, background_1->green); + png_composite_16(w, v, a, png_ptr->background_1.green); + if (!optimize) + w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; - x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; - *(dp + 2) = (png_byte)((x >> 8) & 0xff); - *(dp + 3) = (png_byte)(x & 0xff); + *(sp + 2) = (png_byte)((w >> 8) & 0xff); + *(sp + 3) = (png_byte)(w & 0xff); v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; - png_composite_16(w, v, a, background_1->blue); + png_composite_16(w, v, a, png_ptr->background_1.blue); + if (!optimize) + w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8]; - x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8]; - *(dp + 4) = (png_byte)((x >> 8) & 0xff); - *(dp + 5) = (png_byte)(x & 0xff); + *(sp + 4) = (png_byte)((w >> 8) & 0xff); + *(sp + 5) = (png_byte)(w & 0xff); } } } @@ -3414,28 +4058,22 @@ png_do_background(png_row_infop row_info, png_bytep row, #endif { sp = row; - dp = row; - for (i = 0; i < row_width; i++, sp += 8, dp += 6) + for (i = 0; i < row_width; i++, sp += 8) { png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) << 8) + (png_uint_16)(*(sp + 7))); - if (a == (png_uint_16)0xffff) - { - png_memcpy(dp, sp, 6); - } - - else if (a == 0) + if (a == 0) { - *dp = (png_byte)((background->red >> 8) & 0xff); - *(dp + 1) = (png_byte)(background->red & 0xff); - *(dp + 2) = (png_byte)((background->green >> 8) & 0xff); - *(dp + 3) = (png_byte)(background->green & 0xff); - *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff); - *(dp + 5) = (png_byte)(background->blue & 0xff); + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); } - else + else if (a < 0xffff) { png_uint_16 v; @@ -3445,17 +4083,17 @@ png_do_background(png_row_infop row_info, png_bytep row, png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + *(sp + 5)); - png_composite_16(v, r, a, background->red); - *dp = (png_byte)((v >> 8) & 0xff); - *(dp + 1) = (png_byte)(v & 0xff); + png_composite_16(v, r, a, png_ptr->background.red); + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); - png_composite_16(v, g, a, background->green); - *(dp + 2) = (png_byte)((v >> 8) & 0xff); - *(dp + 3) = (png_byte)(v & 0xff); + png_composite_16(v, g, a, png_ptr->background.green); + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); - png_composite_16(v, b, a, background->blue); - *(dp + 4) = (png_byte)((v >> 8) & 0xff); - *(dp + 5) = (png_byte)(v & 0xff); + png_composite_16(v, b, a, png_ptr->background.blue); + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); } } } @@ -3466,16 +4104,6 @@ png_do_background(png_row_infop row_info, png_bytep row, default: break; } - - if (row_info->color_type & PNG_COLOR_MASK_ALPHA) - { - row_info->color_type = (png_byte)(row_info->color_type & - ~PNG_COLOR_MASK_ALPHA); - row_info->channels--; - row_info->pixel_depth = (png_byte)(row_info->channels * - row_info->bit_depth); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); - } } } #endif @@ -3488,10 +4116,12 @@ png_do_background(png_row_infop row_info, png_bytep row, * build_gamma_table(). */ void /* PRIVATE */ -png_do_gamma(png_row_infop row_info, png_bytep row, - png_const_bytep gamma_table, png_const_uint_16pp gamma_16_table, - int gamma_shift) +png_do_gamma(png_row_infop row_info, png_bytep row, png_structp png_ptr) { + png_const_bytep gamma_table = png_ptr->gamma_table; + png_const_uint_16pp gamma_16_table = png_ptr->gamma_16_table; + int gamma_shift = png_ptr->gamma_shift; + png_bytep sp; png_uint_32 i; png_uint_32 row_width=row_info->width; @@ -3681,6 +4311,73 @@ png_do_gamma(png_row_infop row_info, png_bytep row, } #endif +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED +/* Encode the alpha channel to the output gamma (the input channel is always + * linear.) Called only with color types that have an alpha channel. Needs the + * from_1 tables. + */ +void /* PRIVATE */ +png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structp png_ptr) +{ + png_uint_32 row_width = row_info->width; + + png_debug(1, "in png_do_encode_alpha"); + + if (row_info->color_type & PNG_COLOR_MASK_ALPHA) + { + if (row_info->bit_depth == 8) + { + PNG_CONST png_bytep table = png_ptr->gamma_from_1; + + if (table != NULL) + { + PNG_CONST int step = + (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2; + + /* The alpha channel is the last component: */ + row += step - 1; + + for (; row_width > 0; --row_width, row += step) + *row = table[*row]; + + return; + } + } + + else if (row_info->bit_depth == 16) + { + PNG_CONST png_uint_16pp table = png_ptr->gamma_16_from_1; + PNG_CONST int gamma_shift = png_ptr->gamma_shift; + + if (table != NULL) + { + PNG_CONST int step = + (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4; + + /* The alpha channel is the last component: */ + row += step - 2; + + for (; row_width > 0; --row_width, row += step) + { + png_uint_16 v; + + v = table[*(row + 1) >> gamma_shift][*row]; + *row = (png_byte)((v >> 8) & 0xff); + *(row + 1) = (png_byte)(v & 0xff); + } + + return; + } + } + } + + /* Only get to here if called with a weird row_info; no harm has been done, + * so just issue a warning. + */ + png_warning(png_ptr, "png_do_encode_alpha: unexpected call"); +} +#endif + #ifdef PNG_READ_EXPAND_SUPPORTED /* Expands a palette row to an RGB or RGBA row depending * upon whether you supply trans and num_trans. @@ -3786,7 +4483,7 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, if (row_info->bit_depth == 8) { { - if (trans_alpha != NULL) + if (num_trans > 0) { sp = row + (png_size_t)row_width - 1; dp = row + (png_size_t)(row_width << 2) - 1; @@ -3840,7 +4537,7 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, */ void /* PRIVATE */ png_do_expand(png_row_infop row_info, png_bytep row, - png_const_color_16p trans_value) + png_const_color_16p trans_color) { int shift, value; png_bytep sp, dp; @@ -3852,7 +4549,7 @@ png_do_expand(png_row_infop row_info, png_bytep row, { if (row_info->color_type == PNG_COLOR_TYPE_GRAY) { - png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0); + png_uint_16 gray = (png_uint_16)(trans_color ? trans_color->gray : 0); if (row_info->bit_depth < 8) { @@ -3944,7 +4641,7 @@ png_do_expand(png_row_infop row_info, png_bytep row, row_info->rowbytes = row_width; } - if (trans_value != NULL) + if (trans_color != NULL) { if (row_info->bit_depth == 8) { @@ -3996,13 +4693,13 @@ png_do_expand(png_row_infop row_info, png_bytep row, row_width); } } - else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value) + else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_color) { if (row_info->bit_depth == 8) { - png_byte red = (png_byte)(trans_value->red & 0xff); - png_byte green = (png_byte)(trans_value->green & 0xff); - png_byte blue = (png_byte)(trans_value->blue & 0xff); + png_byte red = (png_byte)(trans_color->red & 0xff); + png_byte green = (png_byte)(trans_color->green & 0xff); + png_byte blue = (png_byte)(trans_color->blue & 0xff); sp = row + (png_size_t)row_info->rowbytes - 1; dp = row + (png_size_t)(row_width << 2) - 1; for (i = 0; i < row_width; i++) @@ -4020,12 +4717,12 @@ png_do_expand(png_row_infop row_info, png_bytep row, } else if (row_info->bit_depth == 16) { - png_byte red_high = (png_byte)((trans_value->red >> 8) & 0xff); - png_byte green_high = (png_byte)((trans_value->green >> 8) & 0xff); - png_byte blue_high = (png_byte)((trans_value->blue >> 8) & 0xff); - png_byte red_low = (png_byte)(trans_value->red & 0xff); - png_byte green_low = (png_byte)(trans_value->green & 0xff); - png_byte blue_low = (png_byte)(trans_value->blue & 0xff); + png_byte red_high = (png_byte)((trans_color->red >> 8) & 0xff); + png_byte green_high = (png_byte)((trans_color->green >> 8) & 0xff); + png_byte blue_high = (png_byte)((trans_color->blue >> 8) & 0xff); + png_byte red_low = (png_byte)(trans_color->red & 0xff); + png_byte green_low = (png_byte)(trans_color->green & 0xff); + png_byte blue_low = (png_byte)(trans_color->blue & 0xff); sp = row + row_info->rowbytes - 1; dp = row + (png_size_t)(row_width << 3) - 1; for (i = 0; i < row_width; i++) @@ -4064,6 +4761,37 @@ png_do_expand(png_row_infop row_info, png_bytep row, } #endif +#ifdef PNG_READ_EXPAND_16_SUPPORTED +/* If the bit depth is 8 and the colour type is not a palette type expand the + * whole row to 16 bits. Has no effect otherwise. + */ +void /* PRIVATE */ +png_do_expand_16(png_row_infop row_info, png_bytep row) +{ + if (row_info->bit_depth == 8 && + row_info->color_type != PNG_COLOR_TYPE_PALETTE) + { + /* The row have a sequence of bytes containing [0..255] and we need + * to turn it into another row containing [0..65535], to do this we + * calculate: + * + * (input / 255) * 65535 + * + * Which happens to be exactly input * 257 and this can be achieved + * simply by byte replication in place (copying backwards). + */ + png_byte *sp = row + row_info->rowbytes; /* source, last byte + 1 */ + png_byte *dp = sp + row_info->rowbytes; /* destination, end + 1 */ + while (dp > sp) + dp[-2] = dp[-1] = *--sp, dp -= 2; + + row_info->rowbytes *= 2; + row_info->bit_depth = 16; + row_info->pixel_depth = (png_byte)(row_info->channels * 16); + } +} +#endif + #ifdef PNG_READ_QUANTIZE_SUPPORTED void /* PRIVATE */ png_do_quantize(png_row_infop row_info, png_bytep row, @@ -4157,6 +4885,7 @@ png_do_quantize(png_row_infop row_info, png_bytep row, } } #endif /* PNG_READ_QUANTIZE_SUPPORTED */ +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ #ifdef PNG_MNG_FEATURES_SUPPORTED /* Undoes intrapixel differencing */ diff --git a/src/3rdparty/libpng/pngrutil.c b/src/3rdparty/libpng/pngrutil.c index 4c3cd53..07e46e2 100644 --- a/src/3rdparty/libpng/pngrutil.c +++ b/src/3rdparty/libpng/pngrutil.c @@ -1,7 +1,7 @@ /* pngrutil.c - utilities to read a PNG file * - * Last changed in libpng 1.5.1 [February 3, 2011] + * Last changed in libpng 1.5.4 [July 7, 2011] * Copyright (c) 1998-2011 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -278,8 +278,7 @@ png_crc_error(png_structp png_ptr) return (0); } -#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \ - defined(PNG_READ_iCCP_SUPPORTED) +#ifdef PNG_READ_COMPRESSED_TEXT_SUPPORTED static png_size_t png_inflate(png_structp png_ptr, png_bytep data, png_size_t size, png_bytep output, png_size_t output_size) @@ -370,41 +369,31 @@ png_inflate(png_structp png_ptr, png_bytep data, png_size_t size, * and the error message is dumped into the uncompressed * buffer if available. */ +# ifdef PNG_WARNINGS_SUPPORTED { - PNG_CONST char *msg; -#ifdef PNG_CONSOLE_IO_SUPPORTED - char umsg[52]; -#endif + png_const_charp msg; + if (png_ptr->zstream.msg != 0) msg = png_ptr->zstream.msg; - else + else switch (ret) { -#ifdef PNG_CONSOLE_IO_SUPPORTED - switch (ret) - { - case Z_BUF_ERROR: - msg = "Buffer error in compressed datastream in %s chunk"; - break; + case Z_BUF_ERROR: + msg = "Buffer error in compressed datastream"; + break; - case Z_DATA_ERROR: - msg = "Data error in compressed datastream in %s chunk"; - break; + case Z_DATA_ERROR: + msg = "Data error in compressed datastream"; + break; - default: - msg = "Incomplete compressed datastream in %s chunk"; - break; - } - - png_snprintf(umsg, sizeof umsg, msg, png_ptr->chunk_name); - msg = umsg; -#else - msg = "Damaged compressed datastream in chunk other than IDAT"; -#endif + default: + msg = "Incomplete compressed datastream"; + break; } - png_warning(png_ptr, msg); + png_chunk_warning(png_ptr, msg); } +# endif /* 0 means an error - notice that this code simply ignores * zero length compressed chunks as a result. @@ -438,8 +427,8 @@ png_decompress_chunk(png_structp png_ptr, int comp_type, png_size_t expanded_size = png_inflate(png_ptr, (png_bytep)(png_ptr->chunkdata + prefix_size), chunklength - prefix_size, - 0, /*output*/ - 0); /*output size*/ + 0, /* output */ + 0); /* output size */ /* Now check the limits on this chunk - if the limit fails the * compressed data will be removed, the prefix will remain. @@ -500,15 +489,9 @@ png_decompress_chunk(png_structp png_ptr, int comp_type, else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */ { -#ifdef PNG_STDIO_SUPPORTED - char umsg[50]; - - png_snprintf(umsg, sizeof umsg, - "Unknown zTXt compression type %d", comp_type); - png_warning(png_ptr, umsg); -#else - png_warning(png_ptr, "Unknown zTXt compression type"); -#endif + PNG_WARNING_PARAMETERS(p) + png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_d, comp_type); + png_formatted_warning(png_ptr, p, "Unknown zTXt compression type @1"); /* The recovery is to simply drop the data. */ } @@ -536,7 +519,7 @@ png_decompress_chunk(png_structp png_ptr, int comp_type, *newlength = prefix_size; } -#endif +#endif /* PNG_READ_COMPRESSED_TEXT_SUPPORTED */ /* Read and check the IDHR chunk */ void /* PRIVATE */ @@ -846,12 +829,10 @@ png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { if (PNG_OUT_OF_RANGE(igamma, 45500L, 500)) { - png_warning(png_ptr, - "Ignoring incorrect gAMA value when sRGB is also present"); - -# ifdef PNG_CONSOLE_IO_SUPPORTED - fprintf(stderr, "gamma = (%d/100000)", (int)igamma); -# endif + PNG_WARNING_PARAMETERS(p) + png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_fixed, igamma); + png_formatted_warning(png_ptr, p, + "Ignoring incorrect gAMA value @1 when sRGB is also present"); return; } } @@ -1020,21 +1001,52 @@ png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) PNG_OUT_OF_RANGE(x_blue, 15000, 1000) || PNG_OUT_OF_RANGE(y_blue, 6000, 1000)) { - png_warning(png_ptr, - "Ignoring incorrect cHRM value when sRGB is also present"); - -#ifdef PNG_CONSOLE_IO_SUPPORTED - fprintf(stderr, "wx=%d, wy=%d, rx=%d, ry=%d\n", - x_white, y_white, x_red, y_red); - - fprintf(stderr, "gx=%d, gy=%d, bx=%d, by=%d\n", - x_green, y_green, x_blue, y_blue); -#endif /* PNG_CONSOLE_IO_SUPPORTED */ + PNG_WARNING_PARAMETERS(p) + + png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_fixed, x_white); + png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_fixed, y_white); + png_warning_parameter_signed(p, 3, PNG_NUMBER_FORMAT_fixed, x_red); + png_warning_parameter_signed(p, 4, PNG_NUMBER_FORMAT_fixed, y_red); + png_warning_parameter_signed(p, 5, PNG_NUMBER_FORMAT_fixed, x_green); + png_warning_parameter_signed(p, 6, PNG_NUMBER_FORMAT_fixed, y_green); + png_warning_parameter_signed(p, 7, PNG_NUMBER_FORMAT_fixed, x_blue); + png_warning_parameter_signed(p, 8, PNG_NUMBER_FORMAT_fixed, y_blue); + + png_formatted_warning(png_ptr, p, + "Ignoring incorrect cHRM white(@1,@2) r(@3,@4)g(@5,@6)b(@7,@8) " + "when sRGB is also present"); } return; } #endif /* PNG_READ_sRGB_SUPPORTED */ +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + /* Store the _white values as default coefficients for the rgb to gray + * operation if it is supported. + */ + if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 0) + { + /* png_set_background has not been called, the coefficients must be in + * range for the following to work without overflow. + */ + if (y_red <= (1<<17) && y_green <= (1<<17) && y_blue <= (1<<17)) + { + /* The y values are chromaticities: Y/X+Y+Z, the weights for the gray + * transformation are simply the normalized Y values for red, green and + * blue scaled by 32768. + */ + png_uint_32 w = y_red + y_green + y_blue; + + png_ptr->rgb_to_gray_red_coeff = (png_uint_16)(((png_uint_32)y_red * + 32768)/w); + png_ptr->rgb_to_gray_green_coeff = (png_uint_16)(((png_uint_32)y_green + * 32768)/w); + png_ptr->rgb_to_gray_blue_coeff = (png_uint_16)(((png_uint_32)y_blue * + 32768)/w); + } + } +#endif + png_set_cHRM_fixed(png_ptr, info_ptr, x_white, y_white, x_red, y_red, x_green, y_green, x_blue, y_blue); } @@ -1096,11 +1108,13 @@ png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { if (PNG_OUT_OF_RANGE(info_ptr->gamma, 45500L, 500)) { - png_warning(png_ptr, - "Ignoring incorrect gAMA value when sRGB is also present"); -#ifdef PNG_CONSOLE_IO_SUPPORTED - fprintf(stderr, "incorrect gamma=(%d/100000)\n", info_ptr->gamma); -#endif + PNG_WARNING_PARAMETERS(p) + + png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_fixed, + info_ptr->gamma); + + png_formatted_warning(png_ptr, p, + "Ignoring incorrect gAMA value @1 when sRGB is also present"); } } #endif /* PNG_READ_gAMA_SUPPORTED */ @@ -1240,23 +1254,15 @@ png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) /* And the following guarantees that profile_size == profile_length. */ if (profile_size > profile_length) { + PNG_WARNING_PARAMETERS(p) + png_free(png_ptr, png_ptr->chunkdata); png_ptr->chunkdata = NULL; -#ifdef PNG_STDIO_SUPPORTED - { - char umsg[80]; - - png_snprintf2(umsg, 80, - "Ignoring iCCP chunk with declared size = %u " - "and actual length = %u", - (unsigned int) profile_size, - (unsigned int) profile_length); - png_warning(png_ptr, umsg); - } -#else - png_warning(png_ptr, - "Ignoring iCCP chunk with uncompressed size mismatch"); -#endif + + png_warning_parameter_unsigned(p, 1, PNG_NUMBER_FORMAT_u, profile_size); + png_warning_parameter_unsigned(p, 2, PNG_NUMBER_FORMAT_u, profile_length); + png_formatted_warning(png_ptr, p, + "Ignoring iCCP chunk with declared size = @1 and actual length = @2"); return; } @@ -1275,9 +1281,7 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { png_bytep entry_start; png_sPLT_t new_palette; -#ifdef PNG_POINTER_INDEXING_SUPPORTED png_sPLT_entryp pp; -#endif png_uint_32 data_length; int entry_size, i; png_uint_32 skip = 0; @@ -1442,7 +1446,7 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2; } - pp->frequency = png_get_uint_16(entry_start); entry_start += 2; + pp[i].frequency = png_get_uint_16(entry_start); entry_start += 2; } #endif @@ -1567,6 +1571,7 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) { png_size_t truelen; png_byte buf[6]; + png_color_16 background; png_debug(1, "in png_handle_bKGD"); @@ -1623,7 +1628,7 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) */ if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) { - png_ptr->background.index = buf[0]; + background.index = buf[0]; if (info_ptr && info_ptr->num_palette) { @@ -1633,33 +1638,36 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) return; } - png_ptr->background.red = - (png_uint_16)png_ptr->palette[buf[0]].red; + background.red = (png_uint_16)png_ptr->palette[buf[0]].red; + background.green = (png_uint_16)png_ptr->palette[buf[0]].green; + background.blue = (png_uint_16)png_ptr->palette[buf[0]].blue; + } - png_ptr->background.green = - (png_uint_16)png_ptr->palette[buf[0]].green; + else + background.red = background.green = background.blue = 0; - png_ptr->background.blue = - (png_uint_16)png_ptr->palette[buf[0]].blue; - } + background.gray = 0; } else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */ { - png_ptr->background.red = - png_ptr->background.green = - png_ptr->background.blue = - png_ptr->background.gray = png_get_uint_16(buf); + background.index = 0; + background.red = + background.green = + background.blue = + background.gray = png_get_uint_16(buf); } else { - png_ptr->background.red = png_get_uint_16(buf); - png_ptr->background.green = png_get_uint_16(buf + 2); - png_ptr->background.blue = png_get_uint_16(buf + 4); + background.index = 0; + background.red = png_get_uint_16(buf); + background.green = png_get_uint_16(buf + 2); + background.blue = png_get_uint_16(buf + 4); + background.gray = 0; } - png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background)); + png_set_bKGD(png_ptr, info_ptr, &background); } #endif @@ -1984,6 +1992,14 @@ png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) return; } + /* Need unit type, width, \0, height: minimum 4 bytes */ + else if (length < 4) + { + png_warning(png_ptr, "sCAL chunk too short"); + png_crc_finish(png_ptr, length); + return; + } + png_debug1(2, "Allocating and reading sCAL chunk data (%u bytes)", length + 1); @@ -2019,23 +2035,29 @@ png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) /* Validate the ASCII numbers, need two ASCII numbers separated by * a '\0' and they need to fit exactly in the chunk data. */ - i = 0; + i = 1; state = 0; - if (png_ptr->chunkdata[1] == 45 /* negative width */ || - !png_check_fp_number(png_ptr->chunkdata, slength, &state, &i) || + if (!png_check_fp_number(png_ptr->chunkdata, slength, &state, &i) || i >= slength || png_ptr->chunkdata[i++] != 0) png_warning(png_ptr, "Invalid sCAL chunk ignored: bad width format"); + else if (!PNG_FP_IS_POSITIVE(state)) + png_warning(png_ptr, "Invalid sCAL chunk ignored: non-positive width"); + else { png_size_t heighti = i; - if (png_ptr->chunkdata[i] == 45 /* negative height */ || - !png_check_fp_number(png_ptr->chunkdata, slength, &state, &i) || + state = 0; + if (!png_check_fp_number(png_ptr->chunkdata, slength, &state, &i) || i != slength) png_warning(png_ptr, "Invalid sCAL chunk ignored: bad height format"); + else if (!PNG_FP_IS_POSITIVE(state)) + png_warning(png_ptr, + "Invalid sCAL chunk ignored: non-positive height"); + else /* This is the (only) success case. */ png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], @@ -2662,6 +2684,14 @@ png_combine_row(png_structp png_ptr, png_bytep row, int mask) { png_debug(1, "in png_combine_row"); + /* Added in 1.5.4: the row_info should match the information returned by any + * call to png_read_update_info at this point. Do not continue if we got + * this wrong. + */ + if (png_ptr->info_rowbytes != 0 && png_ptr->info_rowbytes != + PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width)) + png_error(png_ptr, "internal row size calculation error"); + if (mask == 0xff) { png_memcpy(row, png_ptr->row_buf + 1, @@ -3400,7 +3430,9 @@ png_read_start_row(png_structp png_ptr) png_debug(1, "in png_read_start_row"); png_ptr->zstream.avail_in = 0; +#ifdef PNG_READ_TRANSFORMS_SUPPORTED png_init_read_transformations(png_ptr); +#endif #ifdef PNG_READ_INTERLACING_SUPPORTED if (png_ptr->interlaced) { @@ -3463,6 +3495,24 @@ png_read_start_row(png_structp png_ptr) } #endif +#ifdef PNG_READ_EXPAND_16_SUPPORTED + if (png_ptr->transformations & PNG_EXPAND_16) + { +# ifdef PNG_READ_EXPAND_SUPPORTED + /* In fact it is an error if it isn't supported, but checking is + * the safe way. + */ + if (png_ptr->transformations & PNG_EXPAND) + { + if (png_ptr->bit_depth < 16) + max_pixel_depth *= 2; + } + else +# endif + png_ptr->transformations &= ~PNG_EXPAND_16; + } +#endif + #ifdef PNG_READ_FILLER_SUPPORTED if (png_ptr->transformations & (PNG_FILLER)) { diff --git a/src/3rdparty/libpng/pngset.c b/src/3rdparty/libpng/pngset.c index 2cfcf33..7eaad7d 100644 --- a/src/3rdparty/libpng/pngset.c +++ b/src/3rdparty/libpng/pngset.c @@ -1,7 +1,7 @@ /* pngset.c - storage of image information into info struct * - * Last changed in libpng 1.5.1 [February 3, 2011] + * Last changed in libpng 1.5.4 [July 7, 2011] * Copyright (c) 1998-2011 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -94,15 +94,16 @@ png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point if (png_ptr == NULL || info_ptr == NULL) return; - /* Previously these values were limited, however they must be - * wrong, therefore storing them (and setting PNG_INFO_gAMA) - * must be wrong too. + /* Changed in libpng-1.5.4 to limit the values to ensure overflow can't + * occur. Since the fixed point representation is assymetrical it is + * possible for 1/gamma to overflow the limit of 21474 and this means the + * gamma value must be at least 5/100000 and hence at most 20000.0. For + * safety the limits here are a little narrower. The values are 0.00016 to + * 6250.0, which are truely ridiculous gammma values (and will produce + * displays that are all black or all white.) */ - if (file_gamma > (png_fixed_point)PNG_UINT_31_MAX) - png_warning(png_ptr, "Gamma too large, ignored"); - - else if (file_gamma <= 0) - png_warning(png_ptr, "Negative or zero gamma ignored"); + if (file_gamma < 16 || file_gamma > 625000000) + png_warning(png_ptr, "Out of range gamma value ignored"); else { @@ -340,12 +341,12 @@ png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr, if (unit != 1 && unit != 2) png_error(png_ptr, "Invalid sCAL unit"); - if (swidth == NULL || (lengthw = png_strlen(swidth)) <= 0 || - swidth[0] == 45 /*'-'*/ || !png_check_fp_string(swidth, lengthw)) + if (swidth == NULL || (lengthw = png_strlen(swidth)) == 0 || + swidth[0] == 45 /* '-' */ || !png_check_fp_string(swidth, lengthw)) png_error(png_ptr, "Invalid sCAL width"); - if (sheight == NULL || (lengthh = png_strlen(sheight)) <= 0 || - sheight[0] == 45 /*'-'*/ || !png_check_fp_string(sheight, lengthh)) + if (sheight == NULL || (lengthh = png_strlen(sheight)) == 0 || + sheight[0] == 45 /* '-' */ || !png_check_fp_string(sheight, lengthh)) png_error(png_ptr, "Invalid sCAL height"); info_ptr->scal_unit = (png_byte)unit; @@ -545,7 +546,7 @@ png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr, png_set_sRGB(png_ptr, info_ptr, srgb_intent); # ifdef PNG_gAMA_SUPPORTED - png_set_gAMA_fixed(png_ptr, info_ptr, 45455L); + png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE); # endif # ifdef PNG_cHRM_SUPPORTED diff --git a/src/3rdparty/libpng/pngstruct.h b/src/3rdparty/libpng/pngstruct.h index 8d781fa..93b2b3e 100644 --- a/src/3rdparty/libpng/pngstruct.h +++ b/src/3rdparty/libpng/pngstruct.h @@ -5,7 +5,7 @@ * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * - * Last changed in libpng 1.5.0 [January 6, 2011] + * Last changed in libpng 1.5.4 [July 7, 2011] * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -29,11 +29,13 @@ struct png_struct_def { #ifdef PNG_SETJMP_SUPPORTED - jmp_buf png_jmpbuf; /* used in png_error */ + jmp_buf longjmp_buffer; /* used in png_error */ png_longjmp_ptr longjmp_fn;/* setjmp non-local goto function. */ #endif png_error_ptr error_fn; /* function for printing errors and aborting */ +#ifdef PNG_WARNINGS_SUPPORTED png_error_ptr warning_fn; /* function for printing warnings */ +#endif png_voidp error_ptr; /* user supplied struct for error functions */ png_rw_ptr write_data_fn; /* function for writing output data */ png_rw_ptr read_data_fn; /* function for reading input data */ @@ -64,11 +66,36 @@ struct png_struct_def z_stream zstream; /* pointer to decompression structure (below) */ png_bytep zbuf; /* buffer for zlib */ uInt zbuf_size; /* size of zbuf (typically 65536) */ +#ifdef PNG_WRITE_SUPPORTED + +/* Added in 1.5.4: state to keep track of whether the zstream has been + * initialized and if so whether it is for IDAT or some other chunk. + */ +#define PNG_ZLIB_UNINITIALIZED 0 +#define PNG_ZLIB_FOR_IDAT 1 +#define PNG_ZLIB_FOR_TEXT 2 /* anything other than IDAT */ +#define PNG_ZLIB_USE_MASK 3 /* bottom two bits */ +#define PNG_ZLIB_IN_USE 4 /* a flag value */ + + png_uint_32 zlib_state; /* State of zlib initialization */ +/* End of material added at libpng 1.5.4 */ + int zlib_level; /* holds zlib compression level */ int zlib_method; /* holds zlib compression method */ int zlib_window_bits; /* holds zlib compression window bits */ int zlib_mem_level; /* holds zlib compression memory level */ int zlib_strategy; /* holds zlib compression strategy */ +#endif +/* Added at libpng 1.5.4 */ +#if defined(PNG_WRITE_COMPRESSED_TEXT_SUPPORTED) || \ + defined(PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED) + int zlib_text_level; /* holds zlib compression level */ + int zlib_text_method; /* holds zlib compression method */ + int zlib_text_window_bits; /* holds zlib compression window bits */ + int zlib_text_mem_level; /* holds zlib compression memory level */ + int zlib_text_strategy; /* holds zlib compression strategy */ +#endif +/* End of material added at libpng 1.5.4 */ png_uint_32 width; /* width of image in pixels */ png_uint_32 height; /* height of image in pixels */ @@ -84,6 +111,7 @@ struct png_struct_def png_bytep avg_row; /* buffer to save "avg" row when filtering */ png_bytep paeth_row; /* buffer to save "Paeth" row when filtering */ png_row_info row_info; /* used for transformation routines */ + png_size_t info_rowbytes; /* Added in 1.5.4: cache of updated row bytes */ png_uint_32 idat_size; /* current IDAT size for read */ png_uint_32 crc; /* current chunk CRC value */ @@ -108,7 +136,8 @@ struct png_struct_def png_uint_16 filler; /* filler bytes for pixel expansion */ #endif -#ifdef PNG_bKGD_SUPPORTED +#if defined(PNG_bKGD_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) png_byte background_gamma_type; png_fixed_point background_gamma; png_color_16 background; /* background color in screen gamma space */ @@ -209,7 +238,7 @@ struct png_struct_def #endif #ifdef PNG_TIME_RFC1123_SUPPORTED - png_charp time_buffer; /* String to hold RFC 1123 time text */ + char time_buffer[29]; /* String to hold RFC 1123 time text */ #endif /* New members added in libpng-1.0.6 */ diff --git a/src/3rdparty/libpng/pngtest.c b/src/3rdparty/libpng/pngtest.c index cbb7eb2..9084ada 100644 --- a/src/3rdparty/libpng/pngtest.c +++ b/src/3rdparty/libpng/pngtest.c @@ -1,7 +1,7 @@ /* pngtest.c - a simple test program to test libpng * - * Last changed in libpng 1.5.0 [January 6, 2011] + * Last changed in libpng 1.5.4 [July 7, 2011] * Copyright (c) 1998-2011 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -31,6 +31,8 @@ * of files at once by typing "pngtest -m file1.png file2.png ..." */ +#define _POSIX_SOURCE 1 + #include "zlib.h" #include "png.h" /* Copied from pngpriv.h but only used in error messages below. */ @@ -779,7 +781,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) int bit_depth, color_type; #ifdef PNG_SETJMP_SUPPORTED #ifdef USE_FAR_KEYWORD - jmp_buf png_jmpbuf; + jmp_buf tmp_jmpbuf; #endif #endif @@ -848,7 +850,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) #ifdef PNG_SETJMP_SUPPORTED pngtest_debug("Setting jmpbuf for read struct"); #ifdef USE_FAR_KEYWORD - if (setjmp(png_jmpbuf)) + if (setjmp(tmp_jmpbuf)) #else if (setjmp(png_jmpbuf(read_ptr))) #endif @@ -866,14 +868,14 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) return (1); } #ifdef USE_FAR_KEYWORD - png_memcpy(png_jmpbuf(read_ptr), png_jmpbuf, png_sizeof(jmp_buf)); + png_memcpy(png_jmpbuf(read_ptr), tmp_jmpbuf, png_sizeof(jmp_buf)); #endif #ifdef PNG_WRITE_SUPPORTED pngtest_debug("Setting jmpbuf for write struct"); #ifdef USE_FAR_KEYWORD - if (setjmp(png_jmpbuf)) + if (setjmp(tmp_jmpbuf)) #else if (setjmp(png_jmpbuf(write_ptr))) #endif @@ -890,7 +892,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) } #ifdef USE_FAR_KEYWORD - png_memcpy(png_jmpbuf(write_ptr), png_jmpbuf, png_sizeof(jmp_buf)); + png_memcpy(png_jmpbuf(write_ptr), tmp_jmpbuf, png_sizeof(jmp_buf)); #endif #endif #endif @@ -913,6 +915,14 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) # endif #endif +#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED + /* Normally one would use Z_DEFAULT_STRATEGY for text compression. + * This is here just to make pngtest replicate the results from libpng + * versions prior to 1.5.4, and to test this new API. + */ + png_set_text_compression_strategy(write_ptr, Z_FILTERED); +#endif + if (status_dots_requested == 1) { #ifdef PNG_WRITE_SUPPORTED @@ -1784,4 +1794,4 @@ main(int argc, char *argv[]) } /* Generate a compiler error if there is an old png.h in the search path. */ -typedef png_libpng_version_1_5_1 Your_png_h_is_not_version_1_5_1; +typedef png_libpng_version_1_5_4 Your_png_h_is_not_version_1_5_4; diff --git a/src/3rdparty/libpng/pngtrans.c b/src/3rdparty/libpng/pngtrans.c index 137f555..6a6908d 100644 --- a/src/3rdparty/libpng/pngtrans.c +++ b/src/3rdparty/libpng/pngtrans.c @@ -1,7 +1,7 @@ /* pngtrans.c - transforms the data in a row (used by both readers and writers) * - * Last changed in libpng 1.5.1 [February 3, 2011] + * Last changed in libpng 1.5.4 [July 7, 2011] * Copyright (c) 1998-2011 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -424,170 +424,119 @@ png_do_packswap(png_row_infop row_info, png_bytep row) #if defined(PNG_WRITE_FILLER_SUPPORTED) || \ defined(PNG_READ_STRIP_ALPHA_SUPPORTED) -/* Remove filler or alpha byte(s) */ +/* Remove a channel - this used to be 'png_do_strip_filler' but it used a + * somewhat weird combination of flags to determine what to do. All the calls + * to png_do_strip_filler are changed in 1.5.2 to call this instead with the + * correct arguments. + * + * The routine isn't general - the channel must be the channel at the start or + * end (not in the middle) of each pixel. + */ void /* PRIVATE */ -png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags) +png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start) { - png_debug(1, "in png_do_strip_filler"); - + png_bytep sp = row; /* source pointer */ + png_bytep dp = row; /* destination pointer */ + png_bytep ep = row + row_info->rowbytes; /* One beyond end of row */ + + /* At the start sp will point to the first byte to copy and dp to where + * it is copied to. ep always points just beyond the end of the row, so + * the loop simply copies (channels-1) channels until sp reaches ep. + * + * at_start: 0 -- convert AG, XG, ARGB, XRGB, AAGG, XXGG, etc. + * nonzero -- convert GA, GX, RGBA, RGBX, GGAA, RRGGBBXX, etc. + */ + + /* GA, GX, XG cases */ + if (row_info->channels == 2) { - png_bytep sp = row; - png_bytep dp = row; - png_uint_32 row_width = row_info->width; - png_uint_32 i; - - if ((row_info->color_type == PNG_COLOR_TYPE_RGB || - (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA && - (flags & PNG_FLAG_STRIP_ALPHA))) && - row_info->channels == 4) + if (row_info->bit_depth == 8) { - if (row_info->bit_depth == 8) - { - /* This converts from RGBX or RGBA to RGB */ - if (flags & PNG_FLAG_FILLER_AFTER) - { - dp += 3; sp += 4; - for (i = 1; i < row_width; i++) - { - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - sp++; - } - } + if (at_start) /* Skip initial filler */ + ++sp; + else /* Skip initial channel and, for sp, the filler */ + sp += 2, ++dp; - /* This converts from XRGB or ARGB to RGB */ - else - { - for (i = 0; i < row_width; i++) - { - sp++; - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - } - } - row_info->pixel_depth = 24; - row_info->rowbytes = row_width * 3; - } + /* For a 1 pixel wide image there is nothing to do */ + while (sp < ep) + *dp++ = *sp, sp += 2; - else /* if (row_info->bit_depth == 16) */ - { - if (flags & PNG_FLAG_FILLER_AFTER) - { - /* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */ - sp += 8; dp += 6; - for (i = 1; i < row_width; i++) - { - /* This could be (although png_memcpy is probably slower): - png_memcpy(dp, sp, 6); - sp += 8; - dp += 6; - */ - - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - sp += 2; - } - } + row_info->pixel_depth = 8; + } - else - { - /* This converts from XXRRGGBB or AARRGGBB to RRGGBB */ - for (i = 0; i < row_width; i++) - { - /* This could be (although png_memcpy is probably slower): - png_memcpy(dp, sp, 6); - sp += 8; - dp += 6; - */ - - sp += 2; - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - *dp++ = *sp++; - } - } + else if (row_info->bit_depth == 16) + { + if (at_start) /* Skip initial filler */ + sp += 2; + else /* Skip initial channel and, for sp, the filler */ + sp += 4, dp += 2; - row_info->pixel_depth = 48; - row_info->rowbytes = row_width * 6; - } - row_info->channels = 3; + while (sp < ep) + *dp++ = *sp++, *dp++ = *sp, sp += 3; + + row_info->pixel_depth = 16; } - else if ((row_info->color_type == PNG_COLOR_TYPE_GRAY || - (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && - (flags & PNG_FLAG_STRIP_ALPHA))) && - row_info->channels == 2) - { - if (row_info->bit_depth == 8) - { - if (flags & PNG_FLAG_FILLER_AFTER) - { - /* This converts from GX or GA to G */ - for (i = 0; i < row_width; i++) - { - *dp++ = *sp++; - sp++; - } - } + else + return; /* bad bit depth */ - else - { - /* This converts from XG or AG to G */ - for (i = 0; i < row_width; i++) - { - sp++; - *dp++ = *sp++; - } - } + row_info->channels = 1; - row_info->pixel_depth = 8; - row_info->rowbytes = row_width; - } + /* Finally fix the color type if it records an alpha channel */ + if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + row_info->color_type = PNG_COLOR_TYPE_GRAY; + } - else /* if (row_info->bit_depth == 16) */ - { - if (flags & PNG_FLAG_FILLER_AFTER) - { - /* This converts from GGXX or GGAA to GG */ - sp += 4; dp += 2; - for (i = 1; i < row_width; i++) - { - *dp++ = *sp++; - *dp++ = *sp++; - sp += 2; - } - } + /* RGBA, RGBX, XRGB cases */ + else if (row_info->channels == 4) + { + if (row_info->bit_depth == 8) + { + if (at_start) /* Skip initial filler */ + ++sp; + else /* Skip initial channels and, for sp, the filler */ + sp += 4, dp += 3; - else - { - /* This converts from XXGG or AAGG to GG */ - for (i = 0; i < row_width; i++) - { - sp += 2; - *dp++ = *sp++; - *dp++ = *sp++; - } - } + /* Note that the loop adds 3 to dp and 4 to sp each time. */ + while (sp < ep) + *dp++ = *sp++, *dp++ = *sp++, *dp++ = *sp, sp += 2; - row_info->pixel_depth = 16; - row_info->rowbytes = row_width * 2; + row_info->pixel_depth = 24; + } + + else if (row_info->bit_depth == 16) + { + if (at_start) /* Skip initial filler */ + sp += 2; + else /* Skip initial channels and, for sp, the filler */ + sp += 8, dp += 6; + + while (sp < ep) + { + /* Copy 6 bytes, skip 2 */ + *dp++ = *sp++, *dp++ = *sp++; + *dp++ = *sp++, *dp++ = *sp++; + *dp++ = *sp++, *dp++ = *sp, sp += 3; } - row_info->channels = 1; + + row_info->pixel_depth = 48; } - if (flags & PNG_FLAG_STRIP_ALPHA) - row_info->color_type = (png_byte)(row_info->color_type & - ~PNG_COLOR_MASK_ALPHA); + else + return; /* bad bit depth */ + + row_info->channels = 3; + + /* Finally fix the color type if it records an alpha channel */ + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + row_info->color_type = PNG_COLOR_TYPE_RGB; } + + else + return; /* The filler channel has gone already */ + + /* Fix the rowbytes value. */ + row_info->rowbytes = dp-row; } #endif @@ -703,11 +652,16 @@ png_get_user_transform_ptr(png_const_structp png_ptr) } #endif +#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED png_uint_32 PNGAPI png_get_current_row_number(png_const_structp png_ptr) { + /* See the comments in png.h - this is the sub-image row when reading and + * interlaced image. + */ if (png_ptr != NULL) return png_ptr->row_number; + return PNG_UINT_32_MAX; /* help the app not to fail silently */ } @@ -718,6 +672,7 @@ png_get_current_pass_number(png_const_structp png_ptr) return png_ptr->pass; return 8; /* invalid */ } +#endif /* PNG_USER_TRANSFORM_INFO_SUPPORTED */ #endif /* PNG_READ_USER_TRANSFORM_SUPPORTED || PNG_WRITE_USER_TRANSFORM_SUPPORTED */ #endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff --git a/src/3rdparty/libpng/pngvalid.c b/src/3rdparty/libpng/pngvalid.c index faebe4b..6d1736c 100644 --- a/src/3rdparty/libpng/pngvalid.c +++ b/src/3rdparty/libpng/pngvalid.c @@ -1,7 +1,7 @@ /* pngvalid.c - validate libpng by constructing then reading png files. * - * Last changed in libpng 1.5.1 [February 3, 2011] + * Last changed in libpng 1.5.4 [July 7, 2011] * Copyright (c) 2011 Glenn Randers-Pehrson * Written by John Cunningham Bowler * @@ -19,6 +19,8 @@ * transformations performed by libpng. */ +#define _POSIX_SOURCE 1 + #include "png.h" #if PNG_LIBPNG_VER < 10500 /* This delibarately lacks the PNG_CONST. */ @@ -46,9 +48,13 @@ typedef png_byte *png_const_bytep; #define PNG_COL_IN_INTERLACE_PASS(x, pass) \ ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1) -/* These are needed too for the defualt build: */ +/* These are needed too for the default build: */ #define PNG_WRITE_16BIT_SUPPORTED #define PNG_READ_16BIT_SUPPORTED + +/* This comes from pnglibconf.h afer 1.5: */ +#define PNG_GAMMA_THRESHOLD_FIXED\ + ((png_fixed_point)(PNG_GAMMA_THRESHOLD * 100000)) #endif #include "zlib.h" /* For crc32 */ @@ -108,6 +114,7 @@ static size_t safecatn(char *buffer, size_t bufsize, size_t pos, int n) return safecat(buffer, bufsize, pos, number); } +#ifdef PNG_READ_TRANSFORMS_SUPPORTED static size_t safecatd(char *buffer, size_t bufsize, size_t pos, double d, int precision) { @@ -115,59 +122,76 @@ static size_t safecatd(char *buffer, size_t bufsize, size_t pos, double d, sprintf(number, "%.*f", precision, d); return safecat(buffer, bufsize, pos, number); } +#endif static PNG_CONST char invalid[] = "invalid"; static PNG_CONST char sep[] = ": "; -/* NOTE: this is indexed by ln2(bit_depth)! */ -static PNG_CONST char *bit_depths[8] = -{ - "1", "2", "4", "8", "16", invalid, invalid, invalid -}; - static PNG_CONST char *colour_types[8] = { "greyscale", invalid, "truecolour", "indexed-colour", "greyscale with alpha", invalid, "truecolour with alpha", invalid }; -/* To get log-bit-depth from bit depth, returns 0 to 7 (7 on error). */ -static unsigned int -log2depth(png_byte bit_depth) +/* Generate random bytes. This uses a boring repeatable algorithm and it + * is implemented here so that it gives the same set of numbers on every + * architecture. It's a linear congruential generator (Knuth or Sedgewick + * "Algorithms") but it comes from the 'feedback taps' table in Horowitz and + * Hill, "The Art of Electronics". + */ +static void +make_random_bytes(png_uint_32* seed, void* pv, size_t size) { - switch (bit_depth) - { - case 1: - return 0; - - case 2: - return 1; + png_uint_32 u0 = seed[0], u1 = seed[1]; + png_bytep bytes = /*no cast required*/pv; - case 4: - return 2; + /* There are thirty three bits, the next bit in the sequence is bit-33 XOR + * bit-20. The top 1 bit is in u1, the bottom 32 are in u0. + */ + size_t i; + for (i=0; i<size; ++i) + { + /* First generate 8 new bits then shift them in at the end. */ + png_uint_32 u = ((u0 >> (20-8)) ^ ((u1 << 7) | (u0 >> (32-7)))) & 0xff; + u1 <<= 8; + u1 |= u0 >> 24; + u0 <<= 8; + u0 |= u; + *bytes++ = (png_byte)u; + } - case 8: - return 3; + seed[0] = u0; + seed[1] = u1; +} - case 16: - return 4; +static void +make_four_random_bytes(png_uint_32* seed, png_bytep bytes) +{ + make_random_bytes(seed, bytes, 4); +} - default: - return 7; - } +static void +randomize(void *pv, size_t size) +{ + static png_uint_32 random_seed[2] = {0x56789abc, 0xd}; + make_random_bytes(random_seed, pv, size); } +#define RANDOMIZE(this) randomize(&(this), sizeof (this)) + /* A numeric ID based on PNG file characteristics. The 'do_interlace' field * simply records whether pngvalid did the interlace itself or whether it - * was done by libpng. Width and height must be less than 256. + * was done by libpng. Width and height must be less than 256. 'palette' is an + * index of the palette to use for formats with a palette (0 otherwise.) */ -#define FILEID(col, depth, interlace, width, height, do_interlace) \ - ((png_uint_32)((col) + ((depth)<<3) + ((interlace)<<8) + \ +#define FILEID(col, depth, palette, interlace, width, height, do_interlace) \ + ((png_uint_32)((col) + ((depth)<<3) + ((palette)<<8) + ((interlace)<<13) + \ (((do_interlace)!=0)<<15) + ((width)<<16) + ((height)<<24))) #define COL_FROM_ID(id) ((png_byte)((id)& 0x7U)) #define DEPTH_FROM_ID(id) ((png_byte)(((id) >> 3) & 0x1fU)) -#define INTERLACE_FROM_ID(id) ((int)(((id) >> 8) & 0x3)) +#define PALETTE_FROM_ID(id) ((int)(((id) >> 8) & 0x1f)) +#define INTERLACE_FROM_ID(id) ((int)(((id) >> 13) & 0x3)) #define DO_INTERLACE_FROM_ID(id) ((int)(((id)>>15) & 1)) #define WIDTH_FROM_ID(id) (((id)>>16) & 0xff) #define HEIGHT_FROM_ID(id) (((id)>>24) & 0xff) @@ -175,20 +199,29 @@ log2depth(png_byte bit_depth) /* Utility to construct a standard name for a standard image. */ static size_t standard_name(char *buffer, size_t bufsize, size_t pos, png_byte colour_type, - int log_bit_depth, int interlace_type, png_uint_32 w, png_uint_32 h, - int do_interlace) + int bit_depth, int npalette, int interlace_type, + png_uint_32 w, png_uint_32 h, int do_interlace) { pos = safecat(buffer, bufsize, pos, colour_types[colour_type]); + if (npalette > 0) + { + pos = safecat(buffer, bufsize, pos, "["); + pos = safecatn(buffer, bufsize, pos, npalette); + pos = safecat(buffer, bufsize, pos, "]"); + } pos = safecat(buffer, bufsize, pos, " "); - pos = safecat(buffer, bufsize, pos, bit_depths[log_bit_depth]); - pos = safecat(buffer, bufsize, pos, " bit "); + pos = safecatn(buffer, bufsize, pos, bit_depth); + pos = safecat(buffer, bufsize, pos, " bit"); if (interlace_type != PNG_INTERLACE_NONE) - pos = safecat(buffer, bufsize, pos, "interlaced"); - if (do_interlace) - pos = safecat(buffer, bufsize, pos, "(pngvalid)"); - else - pos = safecat(buffer, bufsize, pos, "(libpng)"); + { + pos = safecat(buffer, bufsize, pos, " interlaced"); + if (do_interlace) + pos = safecat(buffer, bufsize, pos, "(pngvalid)"); + else + pos = safecat(buffer, bufsize, pos, "(libpng)"); + } + if (w > 0 || h > 0) { pos = safecat(buffer, bufsize, pos, " "); @@ -204,7 +237,7 @@ static size_t standard_name_from_id(char *buffer, size_t bufsize, size_t pos, png_uint_32 id) { return standard_name(buffer, bufsize, pos, COL_FROM_ID(id), - log2depth(DEPTH_FROM_ID(id)), INTERLACE_FROM_ID(id), + DEPTH_FROM_ID(id), PALETTE_FROM_ID(id), INTERLACE_FROM_ID(id), WIDTH_FROM_ID(id), HEIGHT_FROM_ID(id), DO_INTERLACE_FROM_ID(id)); } @@ -225,15 +258,29 @@ standard_name_from_id(char *buffer, size_t bufsize, size_t pos, png_uint_32 id) # define READ_BDHI 3 #endif +/* The following defines the number of different palettes to generate for + * each log bit depth of a colour type 3 standard image. + */ +#define PALETTE_COUNT(bit_depth) ((bit_depth) > 4 ? 1 : 16) + static int -next_format(png_bytep colour_type, png_bytep bit_depth) +next_format(png_bytep colour_type, png_bytep bit_depth, int* palette_number) { if (*bit_depth == 0) { - *colour_type = 0, *bit_depth = 1; + *colour_type = 0, *bit_depth = 1, *palette_number = 0; return 1; } + if (*colour_type == 3) + { + /* Add multiple palettes for colour type 3. */ + if (++*palette_number < PALETTE_COUNT(*bit_depth)) + return 1; + + *palette_number = 0; + } + *bit_depth = (png_byte)(*bit_depth << 1); /* Palette images are restricted to 8 bit depth */ @@ -272,6 +319,7 @@ next_format(png_bytep colour_type, png_bytep bit_depth) } } +#ifdef PNG_READ_TRANSFORMS_SUPPORTED static unsigned int sample(png_const_bytep row, png_byte colour_type, png_byte bit_depth, png_uint_32 x, unsigned int sample_index) @@ -290,8 +338,9 @@ sample(png_const_bytep row, png_byte colour_type, png_byte bit_depth, if (colour_type & 4) bit_index += x; /* Alpha channel */ + /* Multiple channels; select one: */ if (colour_type & (2+4)) - bit_index += sample_index * bit_depth; /* Multiple channels: select one */ + bit_index += sample_index * bit_depth; } /* Return the sample from the row as an integer. */ @@ -308,6 +357,7 @@ sample(png_const_bytep row, png_byte colour_type, png_byte bit_depth, bit_index &= 7; return (result >> (8-bit_index-bit_depth)) & ((1U<<bit_depth)-1); } +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ /* Copy a single pixel, of a given size, from one buffer to another - * while this is basically bit addressed there is an implicit assumption @@ -389,6 +439,14 @@ typedef struct png_store_buffer #define FILE_NAME_SIZE 64 +typedef struct store_palette_entry /* record of a single palette entry */ +{ + png_byte red; + png_byte green; + png_byte blue; + png_byte alpha; +} store_palette_entry, store_palette[256]; + typedef struct png_store_file { struct png_store_file* next; /* as many as you like... */ @@ -396,6 +454,8 @@ typedef struct png_store_file png_uint_32 id; /* must be correct (see FILEID) */ png_size_t datacount; /* In this (the last) buffer */ png_store_buffer data; /* Last buffer in file */ + int npalette; /* Number of entries in palette */ + store_palette_entry* palette; /* May be NULL */ } png_store_file; /* The following is a pool of memory allocated by a single libpng read or write @@ -448,7 +508,9 @@ typedef struct png_store png_store_buffer* next; /* Set when reading */ png_size_t readpos; /* Position in *next */ png_byte* image; /* Buffer for reading interlaced images */ - size_t cb_image; /* Size of this buffer */ + png_size_t cb_image; /* Size of this buffer */ + png_size_t cb_row; /* Row size of the image(s) */ + png_uint_32 image_h; /* Number of rows in a single image */ store_pool read_memory_pool; /* Write fields */ @@ -459,37 +521,20 @@ typedef struct png_store char wname[FILE_NAME_SIZE]; png_store_buffer new; /* The end of the new PNG file being written. */ store_pool write_memory_pool; + store_palette_entry* palette; + int npalette; } png_store; /* Initialization and cleanup */ static void -store_pool_mark(png_byte *mark) +store_pool_mark(png_bytep mark) { - /* Generate a new mark. This uses a boring repeatable algorithm and it is - * implemented here so that it gives the same set of numbers on every - * architecture. It's a linear congruential generator (Knuth or Sedgewick - * "Algorithms") but it comes from the 'feedback taps' table in Horowitz and - * Hill, "The Art of Electronics". - */ - static png_uint_32 u0 = 0x12345678, u1 = 1; + static png_uint_32 store_seed[2] = { 0x12345678, 1}; - /* There are thirty three bits, the next bit in the sequence is bit-33 XOR - * bit-20. The top 1 bit is in u1, the bottom 32 are in u0. - */ - int i; - for (i=0; i<4; ++i) - { - /* First generate 8 new bits then shift them in at the end. */ - png_uint_32 u = ((u0 >> (20-8)) ^ ((u1 << 7) | (u0 >> (32-7)))) & 0xff; - u1 <<= 8; - u1 |= u0 >> 24; - u0 <<= 8; - u0 |= u; - *mark++ = (png_byte)u; - } + make_four_random_bytes(store_seed, mark); } -/* Use this for random 32 bit values, this function makes sure the result is +/* Use this for random 32 bit values; this function makes sure the result is * non-zero. */ static png_uint_32 @@ -544,40 +589,14 @@ store_init(png_store* ps) ps->readpos = 0; ps->image = NULL; ps->cb_image = 0; + ps->cb_row = 0; + ps->image_h = 0; ps->pwrite = NULL; ps->piwrite = NULL; ps->writepos = 0; ps->new.prev = NULL; -} - -/* This somewhat odd function is used when reading an image to ensure that the - * buffer is big enough - this is why a png_structp is available. - */ -static void -store_ensure_image(png_store *ps, png_structp pp, size_t cb) -{ - if (ps->cb_image < cb) - { - if (ps->image != NULL) - { - free(ps->image-1); - ps->cb_image = 0; - } - - /* The buffer is deliberately mis-aligned. */ - ps->image = malloc(cb+1); - if (ps->image == NULL) - png_error(pp, "OOM allocating image buffer"); - - ++(ps->image); - ps->cb_image = cb; - } - - /* And, for error checking, the whole buffer is set to '1' - this - * matches what happens with the 'size' test images on write and also - * matches the unused bits in the test rows. - */ - memset(ps->image, 0xff, cb); + ps->palette = NULL; + ps->npalette = 0; } static void @@ -596,6 +615,12 @@ store_freenew(png_store *ps) { store_freebuffer(&ps->new); ps->writepos = 0; + if (ps->palette != NULL) + { + free(ps->palette); + ps->palette = NULL; + ps->npalette = 0; + } } static void @@ -625,6 +650,12 @@ store_freefile(png_store_file **ppf) store_freebuffer(&(*ppf)->data); (*ppf)->datacount = 0; + if ((*ppf)->palette != NULL) + { + free((*ppf)->palette); + (*ppf)->palette = NULL; + (*ppf)->npalette = 0; + } free(*ppf); *ppf = NULL; } @@ -645,6 +676,10 @@ store_storefile(png_store *ps, png_uint_32 id) pf->datacount = ps->writepos; ps->new.prev = NULL; ps->writepos = 0; + pf->palette = ps->palette; + pf->npalette = ps->npalette; + ps->palette = 0; + ps->npalette = 0; /* And save it. */ pf->next = ps->saved; @@ -691,6 +726,21 @@ store_message(png_store *ps, png_structp pp, char *buffer, size_t bufsize, return pos; } +/* Verbose output to the error stream: */ +static void +store_verbose(png_store *ps, png_structp pp, png_const_charp prefix, + png_const_charp message) +{ + char buffer[512]; + + if (prefix) + fputs(prefix, stderr); + + (void)store_message(ps, pp, buffer, sizeof buffer, 0, message); + fputs(buffer, stderr); + fputc('\n', stderr); +} + /* Log an error or warning - the relevant count is always incremented. */ static void store_log(png_store* ps, png_structp pp, png_const_charp message, int is_error) @@ -704,19 +754,7 @@ store_log(png_store* ps, png_structp pp, png_const_charp message, int is_error) store_message(ps, pp, ps->error, sizeof ps->error, 0, message); if (ps->verbose) - { - char buffer[256]; - size_t pos; - - if (is_error) - pos = safecat(buffer, sizeof buffer, 0, "error: "); - else - pos = safecat(buffer, sizeof buffer, 0, "warning: "); - - store_message(ps, pp, buffer, sizeof buffer, pos, message); - fputs(buffer, stderr); - fputc('\n', stderr); - } + store_verbose(ps, pp, is_error ? "error: " : "warning: ", message); } /* Functions to use as PNG callbacks. */ @@ -746,6 +784,141 @@ store_warning(png_structp pp, png_const_charp message) ps->saw_warning = 1; } +/* These somewhat odd functions are used when reading an image to ensure that + * the buffer is big enough, the png_structp is for errors. + */ +/* Return a single row from the correct image. */ +static png_bytep +store_image_row(PNG_CONST png_store* ps, png_structp pp, int nImage, + png_uint_32 y) +{ + png_size_t coffset = (nImage * ps->image_h + y) * (ps->cb_row + 5) + 2; + + if (ps->image == NULL) + png_error(pp, "no allocated image"); + + if (coffset + ps->cb_row + 3 > ps->cb_image) + png_error(pp, "image too small"); + + return ps->image + coffset; +} + +static void +store_image_free(png_store *ps, png_structp pp) +{ + if (ps->image != NULL) + { + png_bytep image = ps->image; + + if (image[-1] != 0xed || image[ps->cb_image] != 0xfe) + { + if (pp != NULL) + png_error(pp, "png_store image overwrite (1)"); + else + store_log(ps, NULL, "png_store image overwrite (2)", 1); + } + + ps->image = NULL; + ps->cb_image = 0; + --image; + free(image); + } +} + +static void +store_ensure_image(png_store *ps, png_structp pp, int nImages, png_size_t cbRow, + png_uint_32 cRows) +{ + png_size_t cb = nImages * cRows * (cbRow + 5); + + if (ps->cb_image < cb) + { + png_bytep image; + + store_image_free(ps, pp); + + /* The buffer is deliberately mis-aligned. */ + image = malloc(cb+2); + if (image == NULL) + { + /* Called from the startup - ignore the error for the moment. */ + if (pp == NULL) + return; + + png_error(pp, "OOM allocating image buffer"); + } + + /* These magic tags are used to detect overwrites above. */ + ++image; + image[-1] = 0xed; + image[cb] = 0xfe; + + ps->image = image; + ps->cb_image = cb; + } + + /* We have an adequate sized image; lay out the rows. There are 2 bytes at + * the start and three at the end of each (this ensures that the row + * alignment starts out odd - 2+1 and changes for larger images on each row.) + */ + ps->cb_row = cbRow; + ps->image_h = cRows; + + /* For error checking, the whole buffer is set to '1' - this matches what + * happens with the 'size' test images on write and also matches the unused + * bits in the test rows. + */ + memset(ps->image, 0xff, cb); + + /* Then put in the marks. */ + while (--nImages >= 0) + { + png_uint_32 y; + + for (y=0; y<cRows; ++y) + { + png_bytep row = store_image_row(ps, pp, nImages, y); + + /* The markers: */ + row[-2] = 190; + row[-1] = 239; + row[cbRow] = 222; + row[cbRow+1] = 173; + row[cbRow+2] = 17; + } + } +} + +static void +store_image_check(PNG_CONST png_store* ps, png_structp pp, int iImage) +{ + png_const_bytep image = ps->image; + + if (image[-1] != 0xed || image[ps->cb_image] != 0xfe) + png_error(pp, "image overwrite"); + else + { + png_size_t cbRow = ps->cb_row; + png_uint_32 rows = ps->image_h; + + image += iImage * (cbRow+5) * ps->image_h; + + image += 2; /* skip image first row markers */ + + while (rows-- > 0) + { + if (image[-2] != 190 || image[-1] != 239) + png_error(pp, "row start overwritten"); + + if (image[cbRow] != 222 || image[cbRow+1] != 173 || + image[cbRow+2] != 17) + png_error(pp, "row end overwritten"); + + image += cbRow+5; + } + } +} + static void store_write(png_structp pp, png_bytep pb, png_size_t st) { @@ -789,6 +962,7 @@ store_read_buffer_size(png_store *ps) return ps->current->datacount; } +#ifdef PNG_READ_TRANSFORMS_SUPPORTED /* Return total bytes available for read. */ static size_t store_read_buffer_avail(png_store *ps) @@ -813,6 +987,7 @@ store_read_buffer_avail(png_store *ps) return 0; } +#endif static int store_read_buffer_next(png_store *ps) @@ -894,6 +1069,44 @@ store_progressive_read(png_store *ps, png_structp pp, png_infop pi) while (store_read_buffer_next(ps)); } +/* The caller must fill this in: */ +static store_palette_entry * +store_write_palette(png_store *ps, int npalette) +{ + if (ps->pwrite == NULL) + store_log(ps, NULL, "attempt to write palette without write stream", 1); + + if (ps->palette != NULL) + png_error(ps->pwrite, "multiple store_write_palette calls"); + + /* This function can only return NULL if called with '0'! */ + if (npalette > 0) + { + ps->palette = malloc(npalette * sizeof *ps->palette); + + if (ps->palette == NULL) + png_error(ps->pwrite, "store new palette: OOM"); + + ps->npalette = npalette; + } + + return ps->palette; +} + +static store_palette_entry * +store_current_palette(png_store *ps, int *npalette) +{ + /* This is an internal error (the call has been made outside a read + * operation.) + */ + if (ps->current == NULL) + store_log(ps, ps->pread, "no current stream for palette", 1); + + /* The result may be null if there is no palette. */ + *npalette = ps->current->npalette; + return ps->current->palette; +} + /***************************** MEMORY MANAGEMENT*** ***************************/ /* A store_memory is simply the header for an allocated block of memory. The * pointer returned to libpng is just after the end of the header block, the @@ -979,7 +1192,7 @@ store_pool_delete(png_store *ps, store_pool *pool) next->next = NULL; fprintf(stderr, "\t%lu bytes @ %p\n", - (unsigned long)next->size, next+1); + (unsigned long)next->size, (PNG_CONST void*)(next+1)); /* The NULL means this will always return, even if the memory is * corrupted. */ @@ -1258,13 +1471,7 @@ store_delete(png_store *ps) store_write_reset(ps); store_read_reset(ps); store_freefile(&ps->saved); - - if (ps->image != NULL) - { - free(ps->image-1); - ps->image = NULL; - ps->cb_image = 0; - } + store_image_free(ps, NULL); } /*********************** PNG FILE MODIFICATION ON READ ************************/ @@ -1310,11 +1517,19 @@ typedef struct png_modifier */ double maxout8; /* Maximum output value error */ double maxabs8; /* Absolute sample error 0..1 */ + double maxcalc8; /* Absolute sample error 0..1 */ double maxpc8; /* Percentage sample error 0..100% */ double maxout16; /* Maximum output value error */ double maxabs16; /* Absolute sample error 0..1 */ + double maxcalc16;/* Absolute sample error 0..1 */ double maxpc16; /* Percentage sample error 0..100% */ + /* Log limits - values above this are logged, but not necessarily + * warned. + */ + double log8; /* Absolute error in 8 bits to log */ + double log16; /* Absolute error in 16 bits to log */ + /* Logged 8 and 16 bit errors ('output' values): */ double error_gray_2; double error_gray_4; @@ -1322,6 +1537,7 @@ typedef struct png_modifier double error_gray_16; double error_color_8; double error_color_16; + double error_indexed; /* Flags: */ /* Whether or not to interlace. */ @@ -1341,11 +1557,24 @@ typedef struct png_modifier unsigned int use_input_precision_sbit :1; unsigned int use_input_precision_16to8 :1; + /* If set assume that the calculation bit depth is set by the input + * precision, not the output precision. + */ + unsigned int calculations_use_input_precision :1; + + /* If set assume that the calculations are done in 16 bits even if both input + * and output are 8 bit or less. + */ + unsigned int assume_16_bit_calculations :1; + /* Which gamma tests to run: */ unsigned int test_gamma_threshold :1; unsigned int test_gamma_transform :1; /* main tests */ unsigned int test_gamma_sbit :1; - unsigned int test_gamma_strip16 :1; + unsigned int test_gamma_scale16 :1; + unsigned int test_gamma_background :1; + unsigned int test_gamma_alpha_mode :1; + unsigned int test_gamma_expand16 :1; unsigned int log :1; /* Log max error */ @@ -1358,35 +1587,6 @@ typedef struct png_modifier png_byte buffer[1024]; } png_modifier; -static double abserr(png_modifier *pm, png_byte bit_depth) -{ - return bit_depth == 16 ? pm->maxabs16 : pm->maxabs8; -} - -static double pcerr(png_modifier *pm, png_byte bit_depth) -{ - return (bit_depth == 16 ? pm->maxpc16 : pm->maxpc8) * .01; -} - -static double outerr(png_modifier *pm, png_byte bit_depth) -{ - /* There is a serious error in the 2 and 4 bit grayscale transform because - * the gamma table value (8 bits) is simply shifted, not rounded, so the - * error in 4 bit greyscale gamma is up to the value below. This is a hack - * to allow pngvalid to succeed: - */ - if (bit_depth == 2) - return .73182-.5; - - if (bit_depth == 4) - return .90644-.5; - - if (bit_depth == 16) - return pm->maxout16; - - return pm->maxout8; -} - /* This returns true if the test should be stopped now because it has already * failed and it is running silently. */ @@ -1404,10 +1604,14 @@ modifier_init(png_modifier *pm) pm->modifications = NULL; pm->state = modifier_start; pm->sbitlow = 1U; - pm->maxout8 = pm->maxpc8 = pm->maxabs8 = 0; - pm->maxout16 = pm->maxpc16 = pm->maxabs16 = 0; + pm->ngammas = 0; + pm->gammas = 0; + pm->maxout8 = pm->maxpc8 = pm->maxabs8 = pm->maxcalc8 = 0; + pm->maxout16 = pm->maxpc16 = pm->maxabs16 = pm->maxcalc16 = 0; + pm->log8 = pm->log16 = 0; /* Means 'off' */ pm->error_gray_2 = pm->error_gray_4 = pm->error_gray_8 = 0; pm->error_gray_16 = pm->error_color_8 = pm->error_color_16 = 0; + pm->error_indexed = 0; pm->interlace_type = PNG_INTERLACE_NONE; pm->test_standard = 0; pm->test_size = 0; @@ -1415,15 +1619,156 @@ modifier_init(png_modifier *pm) pm->use_input_precision = 0; pm->use_input_precision_sbit = 0; pm->use_input_precision_16to8 = 0; + pm->calculations_use_input_precision = 0; pm->test_gamma_threshold = 0; pm->test_gamma_transform = 0; pm->test_gamma_sbit = 0; - pm->test_gamma_strip16 = 0; + pm->test_gamma_scale16 = 0; + pm->test_gamma_background = 0; + pm->test_gamma_alpha_mode = 0; + pm->test_gamma_expand16 = 0; pm->log = 0; /* Rely on the memset for all the other fields - there are no pointers */ } +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +/* If pm->calculations_use_input_precision is set then operations will happen + * with only 8 bit precision unless both the input and output bit depth are 16. + * + * If pm->assume_16_bit_calculations is set then even 8 bit calculations use 16 + * bit precision. This only affects those of the following limits that pertain + * to a calculation - not a digitization operation! + */ +static double abserr(png_modifier *pm, int in_depth, int out_depth) +{ + /* Absolute error permitted in linear values - affected by the bit depth of + * the calculations. + */ + if (pm->assume_16_bit_calculations || (out_depth == 16 && (in_depth == 16 || + !pm->calculations_use_input_precision))) + return pm->maxabs16; + else + return pm->maxabs8; +} + +static double calcerr(png_modifier *pm, int in_depth, int out_depth) +{ + /* Error in the linear composition arithmetic - only relevant when + * composition actually happens (0 < alpha < 1). + */ + if (pm->assume_16_bit_calculations || (out_depth == 16 && (in_depth == 16 || + !pm->calculations_use_input_precision))) + return pm->maxcalc16; + else + return pm->maxcalc8; +} + +static double pcerr(png_modifier *pm, int in_depth, int out_depth) +{ + /* Percentage error permitted in the linear values. Note that the specified + * value is a percentage but this routine returns a simple number. + */ + if (pm->assume_16_bit_calculations || (out_depth == 16 && (in_depth == 16 || + !pm->calculations_use_input_precision))) + return pm->maxpc16 * .01; + else + return pm->maxpc8 * .01; +} + +/* Output error - the error in the encoded value. This is determined by the + * digitization of the output so can be +/-0.5 in the actual output value. In + * the expand_16 case with the current code in libpng the expand happens after + * all the calculations are done in 8 bit arithmetic, so even though the output + * depth is 16 the output error is determined by the 8 bit calculation. + * + * This limit is not determined by the bit depth of internal calculations. + * + * The specified parameter does *not* include the base .5 digitization error but + * it is added here. + */ +static double outerr(png_modifier *pm, int in_depth, int out_depth) +{ + /* There is a serious error in the 2 and 4 bit grayscale transform because + * the gamma table value (8 bits) is simply shifted, not rounded, so the + * error in 4 bit greyscale gamma is up to the value below. This is a hack + * to allow pngvalid to succeed: + * + * TODO: fix this in libpng + */ + if (out_depth == 2) + return .73182-.5; + + if (out_depth == 4) + return .90644-.5; + + if (out_depth == 16 && (in_depth == 16 || + !pm->calculations_use_input_precision)) + return pm->maxout16; + + /* This is the case where the value was calculated at 8-bit precision then + * scaled to 16 bits. + */ + else if (out_depth == 16) + return pm->maxout8 * 257; + + else + return pm->maxout8; +} + +/* This does the same thing as the above however it returns the value to log, + * rather than raising a warning. This is useful for debugging to track down + * exactly what set of parameters cause high error values. + */ +static double outlog(png_modifier *pm, int in_depth, int out_depth) +{ + /* The command line parameters are either 8 bit (0..255) or 16 bit (0..65535) + * and so must be adjusted for low bit depth grayscale: + */ + if (out_depth <= 8) + { + if (pm->log8 == 0) /* switched off */ + return 256; + + if (out_depth < 8) + return pm->log8 / 255 * ((1<<out_depth)-1); + + return pm->log8; + } + + if (out_depth == 16 && (in_depth == 16 || + !pm->calculations_use_input_precision)) + { + if (pm->log16 == 0) + return 65536; + + return pm->log16; + } + + /* This is the case where the value was calculated at 8-bit precision then + * scaled to 16 bits. + */ + if (pm->log8 == 0) + return 65536; + + return pm->log8 * 257; +} + +/* This complements the above by providing the appropriate quantization for the + * final value. Normally this would just be quantization to an integral value, + * but in the 8 bit calculation case it's actually quantization to a multiple of + * 257! + */ +static int output_quantization_factor(png_modifier *pm, int in_depth, + int out_depth) +{ + if (out_depth == 16 && in_depth != 16 + && pm->calculations_use_input_precision) + return 257; + else + return 1; +} + /* One modification structure must be provided for each chunk to be modified (in * fact more than one can be provided if multiple separate changes are desired * for a single chunk.) Modifications include adding a new chunk when a @@ -1586,7 +1931,7 @@ modifier_read_imp(png_modifier *pm, png_bytep pb, png_size_t st) store_read_imp(&pm->this, pb, cb); pb += cb; st -= cb; - if (st <= 0) return; + if (st == 0) return; } /* No more bytes to flush, read a header, or handle a pending @@ -1813,6 +2158,7 @@ set_modifier_for_read(png_modifier *pm, png_infopp ppi, png_uint_32 id, return set_store_for_read(&pm->this, ppi, id, name); } +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ /***************************** STANDARD PNG FILES *****************************/ /* Standard files - write and save standard files. */ @@ -1840,9 +2186,170 @@ set_modifier_for_read(png_modifier *pm, png_infopp ppi, png_uint_32 id, * a maximum width of 16 pixels (for the 64bpp case.) They also have a maximum * height of 16 rows. The width and height are stored in the FILEID and, being * non-zero, indicate a size file. + * + * For palette image (colour type 3) multiple transform images are stored with + * the same bit depth to allow testing of more colour combinations - + * particularly important for testing the gamma code because libpng uses a + * different code path for palette images. For size images a single palette is + * used. + */ + +/* Make a 'standard' palette. Because there are only 256 entries in a palette + * (maximum) this actually makes a random palette in the hope that enough tests + * will catch enough errors. (Note that the same palette isn't produced every + * time for the same test - it depends on what previous tests have been run - + * but a given set of arguments to pngvalid will always produce the same palette + * at the same test! This is why pseudo-random number generators are useful for + * testing.) + * + * The store must be open for write when this is called, otherwise an internal + * error will occur. This routine contains its own magic number seed, so the + * palettes generated don't change if there are intervening errors (changing the + * calls to the store_mark seed.) + */ +static store_palette_entry * +make_standard_palette(png_store* ps, int npalette, int do_tRNS) +{ + static png_uint_32 palette_seed[2] = { 0x87654321, 9 }; + + int i = 0; + png_byte values[256][4]; + + /* Always put in black and white plus the six primary and secondary colors. + */ + for (; i<8; ++i) + { + values[i][1] = (i&1) ? 255 : 0; + values[i][2] = (i&2) ? 255 : 0; + values[i][3] = (i&4) ? 255 : 0; + } + + /* Then add 62 greys (one quarter of the remaining 256 slots). */ + { + int j = 0; + png_byte random_bytes[4]; + png_byte need[256]; + + need[0] = 0; /*got black*/ + memset(need+1, 1, (sizeof need)-2); /*need these*/ + need[255] = 0; /*but not white*/ + + while (i<70) + { + png_byte b; + + if (j==0) + { + make_four_random_bytes(palette_seed, random_bytes); + j = 4; + } + + b = random_bytes[--j]; + if (need[b]) + { + values[i][1] = b; + values[i][2] = b; + values[i++][3] = b; + } + } + } + + /* Finally add 192 colors at random - don't worry about matches to things we + * already have, chance is less than 1/65536. Don't worry about greys, + * chance is the same, so we get a duplicate or extra gray less than 1 time + * in 170. + */ + for (; i<256; ++i) + make_four_random_bytes(palette_seed, values[i]); + + /* Fill in the alpha values in the first byte. Just use all possible values + * (0..255) in an apparently random order: + */ + { + store_palette_entry *palette; + png_byte selector[4]; + + make_four_random_bytes(palette_seed, selector); + + if (do_tRNS) + for (i=0; i<256; ++i) + values[i][0] = (png_byte)(i ^ selector[0]); + + else + for (i=0; i<256; ++i) + values[i][0] = 255; /* no transparency/tRNS chunk */ + + /* 'values' contains 256 ARGB values, but we only need 'npalette'. + * 'npalette' will always be a power of 2: 2, 4, 16 or 256. In the low + * bit depth cases select colors at random, else it is difficult to have + * a set of low bit depth palette test with any chance of a reasonable + * range of colors. Do this by randomly permuting values into the low + * 'npalette' entries using an XOR mask generated here. This also + * permutes the npalette == 256 case in a potentially useful way (there is + * no relationship between palette index and the color value therein!) + */ + palette = store_write_palette(ps, npalette); + + for (i=0; i<npalette; ++i) + { + palette[i].alpha = values[i ^ selector[1]][0]; + palette[i].red = values[i ^ selector[1]][1]; + palette[i].green = values[i ^ selector[1]][2]; + palette[i].blue = values[i ^ selector[1]][3]; + } + + return palette; + } +} + +/* Initialize a standard palette on a write stream. The 'do_tRNS' argument + * indicates whether or not to also set the tRNS chunk. */ +static void +init_standard_palette(png_store *ps, png_structp pp, png_infop pi, int npalette, + int do_tRNS) +{ + store_palette_entry *ppal = make_standard_palette(ps, npalette, do_tRNS); -/* The number of passes is related to the interlace type. There wass no libpng + { + int i; + png_color palette[256]; + + /* Set all entries to detect overread errors. */ + for (i=0; i<npalette; ++i) + { + palette[i].red = ppal[i].red; + palette[i].green = ppal[i].green; + palette[i].blue = ppal[i].blue; + } + + /* Just in case fill in the rest with detectable values: */ + for (; i<256; ++i) + palette[i].red = palette[i].green = palette[i].blue = 42; + + png_set_PLTE(pp, pi, palette, npalette); + } + + if (do_tRNS) + { + int i, j; + png_byte tRNS[256]; + + /* Set all the entries, but skip trailing opaque entries */ + for (i=j=0; i<npalette; ++i) + if ((tRNS[i] = ppal[i].alpha) < 255) + j = i+1; + + /* Fill in the remainder with a detectable value: */ + for (; i<256; ++i) + tRNS[i] = 24; + + if (j > 0) + png_set_tRNS(pp, pi, tRNS, j, 0/*color*/); + } +} + +/* The number of passes is related to the interlace type. There was no libpng * API to determine this prior to 1.5, so we need an inquiry function: */ static int @@ -1866,6 +2373,8 @@ bit_size(png_structp pp, png_byte colour_type, png_byte bit_depth) { switch (colour_type) { + default: png_error(pp, "invalid color type"); + case 0: return bit_depth; case 2: return 3*bit_depth; @@ -1875,8 +2384,6 @@ bit_size(png_structp pp, png_byte colour_type, png_byte bit_depth) case 4: return 2*bit_depth; case 6: return 4*bit_depth; - - default: png_error(pp, "invalid color type"); } } @@ -1884,12 +2391,7 @@ bit_size(png_structp pp, png_byte colour_type, png_byte bit_depth) #define TRANSFORM_ROWMAX (TRANSFORM_WIDTH*8U) #define SIZE_ROWMAX (16*8U) /* 16 pixels, max 8 bytes each - 128 bytes */ #define STANDARD_ROWMAX TRANSFORM_ROWMAX /* The larger of the two */ - -/* So the maximum image sizes are as follows. A 'transform' image may require - * more than 65535 bytes. The size images are a maximum of 2046 bytes. - */ -#define TRANSFORM_IMAGEMAX (TRANSFORM_ROWMAX * (png_uint_32)2048) -#define SIZE_IMAGEMAX (SIZE_ROWMAX * 16U) +#define SIZE_HEIGHTMAX 16 /* Maximum range of size images */ static size_t transform_rowsize(png_structp pp, png_byte colour_type, png_byte bit_depth) @@ -1925,6 +2427,7 @@ transform_height(png_structp pp, png_byte colour_type, png_byte bit_depth) case 48: case 64: return 2048;/* 4 x 65536 pixels. */ +# define TRANSFORM_HEIGHTMAX 2048 default: return 0; /* Error, will be caught later */ @@ -2088,7 +2591,8 @@ transform_row(png_structp pp, png_byte buffer[TRANSFORM_ROWMAX], */ static void make_transform_image(png_store* PNG_CONST ps, png_byte PNG_CONST colour_type, - png_byte PNG_CONST bit_depth, int interlace_type, png_const_charp name) + png_byte PNG_CONST bit_depth, int palette_number, int interlace_type, + png_const_charp name) { context(ps, fault); @@ -2111,17 +2615,32 @@ make_transform_image(png_store* PNG_CONST ps, png_byte PNG_CONST colour_type, bit_depth, colour_type, interlace_type, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - if (colour_type == 3) /* palette */ +#ifdef PNG_TEXT_SUPPORTED { - unsigned int i = 0; - png_color pal[256]; - - do - pal[i].red = pal[i].green = pal[i].blue = (png_byte)i; - while(++i < 256U); + static char key[] = "image name"; /* must be writeable */ + size_t pos; + png_text text; + char copy[FILE_NAME_SIZE]; - png_set_PLTE(pp, pi, pal, 256); + /* Use a compressed text string to test the correct interaction of text + * compression and IDAT compression. + */ + text.compression = PNG_TEXT_COMPRESSION_zTXt; + text.key = key; + /* Yuck: the text must be writable! */ + pos = safecat(copy, sizeof copy, 0, ps->wname); + text.text = copy; + text.text_length = pos; + text.itxt_length = 0; + text.lang = 0; + text.lang_key = 0; + + png_set_text(pp, pi, &text, 1); } +#endif + + if (colour_type == 3) /* palette */ + init_standard_palette(ps, pp, pi, 1U << bit_depth, 1/*do tRNS*/); png_write_info(pp, pi); @@ -2155,11 +2674,32 @@ make_transform_image(png_store* PNG_CONST ps, png_byte PNG_CONST colour_type, } } +#ifdef PNG_TEXT_SUPPORTED + { + static char key[] = "end marker"; + static char comment[] = "end"; + png_text text; + + /* Use a compressed text string to test the correct interaction of text + * compression and IDAT compression. + */ + text.compression = PNG_TEXT_COMPRESSION_zTXt; + text.key = key; + text.text = comment; + text.text_length = (sizeof comment)-1; + text.itxt_length = 0; + text.lang = 0; + text.lang_key = 0; + + png_set_text(pp, pi, &text, 1); + } +#endif + png_write_end(pp, pi); /* And store this under the appropriate id, then clean up. */ - store_storefile(ps, FILEID(colour_type, bit_depth, interlace_type, - 0, 0, 0)); + store_storefile(ps, FILEID(colour_type, bit_depth, palette_number, + interlace_type, 0, 0, 0)); store_write_reset(ps); } @@ -2175,10 +2715,19 @@ make_transform_image(png_store* PNG_CONST ps, png_byte PNG_CONST colour_type, } static void -make_standard(png_store* PNG_CONST ps, png_byte PNG_CONST colour_type, int bdlo, - int PNG_CONST bdhi) +make_transform_images(png_store *ps) { - for (; bdlo <= bdhi; ++bdlo) + png_byte colour_type = 0; + png_byte bit_depth = 0; + int palette_number = 0; + + /* This is in case of errors. */ + safecat(ps->test, sizeof ps->test, 0, "make standard images"); + + /* Use next_format to enumerate all the combinations we test, including + * generating multiple low bit depth palette images. + */ + while (next_format(&colour_type, &bit_depth, &palette_number)) { int interlace_type; @@ -2187,29 +2736,14 @@ make_standard(png_store* PNG_CONST ps, png_byte PNG_CONST colour_type, int bdlo, { char name[FILE_NAME_SIZE]; - standard_name(name, sizeof name, 0, colour_type, bdlo, interlace_type, - 0, 0, 0); - make_transform_image(ps, colour_type, DEPTH(bdlo), interlace_type, - name); + standard_name(name, sizeof name, 0, colour_type, bit_depth, + palette_number, interlace_type, 0, 0, 0); + make_transform_image(ps, colour_type, bit_depth, palette_number, + interlace_type, name); } } } -static void -make_transform_images(png_store *ps) -{ - /* This is in case of errors. */ - safecat(ps->test, sizeof ps->test, 0, "make standard images"); - - /* Arguments are colour_type, low bit depth, high bit depth - */ - make_standard(ps, 0, 0, WRITE_BDHI); - make_standard(ps, 2, 3, WRITE_BDHI); - make_standard(ps, 3, 0, 3 /*palette: max 8 bits*/); - make_standard(ps, 4, 3, WRITE_BDHI); - make_standard(ps, 6, 3, WRITE_BDHI); -} - /* The following two routines use the PNG interlace support macros from * png.h to interlace or deinterlace rows. */ @@ -2254,7 +2788,7 @@ deinterlace_row(png_bytep buffer, png_const_bytep row, } } -/* Build a single row for the 'size' test images, this fills in only the +/* Build a single row for the 'size' test images; this fills in only the * first bit_width bits of the sample row. */ static void @@ -2294,8 +2828,8 @@ make_size_image(png_store* PNG_CONST ps, png_byte PNG_CONST colour_type, /* Make a name and get an appropriate id for the store: */ char name[FILE_NAME_SIZE]; - PNG_CONST png_uint_32 id = FILEID(colour_type, bit_depth, interlace_type, - w, h, do_interlace); + PNG_CONST png_uint_32 id = FILEID(colour_type, bit_depth, 0/*palette*/, + interlace_type, w, h, do_interlace); standard_name_from_id(name, sizeof name, 0, id); pp = set_store_for_write(ps, &pi, name); @@ -2310,20 +2844,8 @@ make_size_image(png_store* PNG_CONST ps, png_byte PNG_CONST colour_type, png_set_IHDR(pp, pi, w, h, bit_depth, colour_type, interlace_type, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - /* Same palette as make_transform_image - I don' think there is any - * benefit from using a different one (JB 20101211) - */ if (colour_type == 3) /* palette */ - { - unsigned int i = 0; - png_color pal[256]; - - do - pal[i].red = pal[i].green = pal[i].blue = (png_byte)i; - while(++i < 256U); - - png_set_PLTE(pp, pi, pal, 256); - } + init_standard_palette(ps, pp, pi, 1U << bit_depth, 0/*do tRNS*/); png_write_info(pp, pi); @@ -2369,7 +2891,7 @@ make_size_image(png_store* PNG_CONST ps, png_byte PNG_CONST colour_type, png_byte tempRow[SIZE_ROWMAX]; /* If do_interlace *and* the image is interlaced we - * need a reduced interlace row, this may be reduced + * need a reduced interlace row; this may be reduced * to empty. */ if (do_interlace && interlace_type == PNG_INTERLACE_ADAM7) @@ -2480,6 +3002,7 @@ standard_row(png_structp pp, png_byte std[STANDARD_ROWMAX], png_uint_32 id, * to ensure that they get detected - it should not be possible to write an * invalid image with libpng! */ +#ifdef PNG_WARNINGS_SUPPORTED static void sBIT0_error_fn(png_structp pp, png_infop pi) { @@ -2514,6 +3037,7 @@ static PNG_CONST struct unsigned int warning :1; /* the error is a warning... */ } error_test[] = { + /* no warnings makes these errors undetectable. */ { sBIT0_error_fn, "sBIT(0): failed to detect error", 1 }, { sBIT_error_fn, "sBIT(too big): failed to detect error", 1 }, }; @@ -2539,18 +3063,9 @@ make_error(png_store* volatile ps, png_byte PNG_CONST colour_type, interlace_type, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); if (colour_type == 3) /* palette */ - { - unsigned int i = 0; - png_color pal[256]; - - do - pal[i].red = pal[i].green = pal[i].blue = (png_byte)i; - while(++i < 256U); + init_standard_palette(ps, pp, pi, 1U << bit_depth, 0/*do tRNS*/); - png_set_PLTE(pp, pi, pal, 256); - } - - /* Time for a few errors, these are in various optional chunks, the + /* Time for a few errors; these are in various optional chunks, the * standard tests test the standard chunks pretty well. */ # define exception__prev exception_prev_1 @@ -2641,8 +3156,8 @@ make_errors(png_modifier* PNG_CONST pm, png_byte PNG_CONST colour_type, unsigned int test; char name[FILE_NAME_SIZE]; - standard_name(name, sizeof name, 0, colour_type, bdlo, interlace_type, - 0, 0, 0); + standard_name(name, sizeof name, 0, colour_type, 1<<bdlo, 0, + interlace_type, 0, 0, 0); for (test=0; test<(sizeof error_test)/(sizeof error_test[0]); ++test) { @@ -2657,10 +3172,12 @@ make_errors(png_modifier* PNG_CONST pm, png_byte PNG_CONST colour_type, return 1; /* keep going */ } +#endif static void perform_error_test(png_modifier *pm) { +#ifdef PNG_WARNINGS_SUPPORTED /* else there are no cases that work! */ /* Need to do this here because we just write in this test. */ safecat(pm->this.test, sizeof pm->this.test, 0, "error test"); @@ -2678,6 +3195,73 @@ perform_error_test(png_modifier *pm) if (!make_errors(pm, 6, 3, WRITE_BDHI)) return; +#else + UNUSED(pm) +#endif +} + +/* This is just to validate the internal PNG formatting code - if this fails + * then the warning messages the library outputs will probably be garbage. + */ +static void +perform_formatting_test(png_store *volatile ps) +{ +#ifdef PNG_TIME_RFC1123_SUPPORTED + /* The handle into the formatting code is the RFC1123 support; this test does + * nothing if that is compiled out. + */ + context(ps, fault); + + Try + { + png_const_charp correct = "29 Aug 2079 13:53:60 +0000"; + png_const_charp result; + png_structp pp; + png_time pt; + + pp = set_store_for_write(ps, NULL, "libpng formatting test"); + + if (pp == NULL) + Throw ps; + + + /* Arbitrary settings: */ + pt.year = 2079; + pt.month = 8; + pt.day = 29; + pt.hour = 13; + pt.minute = 53; + pt.second = 60; /* a leap second */ + + result = png_convert_to_rfc1123(pp, &pt); + + if (result == NULL) + png_error(pp, "png_convert_to_rfc1123 failed"); + + if (strcmp(result, correct) != 0) + { + size_t pos = 0; + char msg[128]; + + pos = safecat(msg, sizeof msg, pos, "png_convert_to_rfc1123("); + pos = safecat(msg, sizeof msg, pos, correct); + pos = safecat(msg, sizeof msg, pos, ") returned: '"); + pos = safecat(msg, sizeof msg, pos, result); + pos = safecat(msg, sizeof msg, pos, "'"); + + png_error(pp, msg); + } + + store_write_reset(ps); + } + + Catch(fault) + { + store_write_reset(fault); + } +#else + UNUSED(ps) +#endif } /* Because we want to use the same code in both the progressive reader and the @@ -2702,16 +3286,8 @@ perform_error_test(png_modifier *pm) * requirement that the pointer to the first member of a structure must be the * same as the pointer to the structure. This allows us to reuse standard_ * functions in the gamma test code; something that could not be done with - * nested funtions! + * nested functions! */ -typedef struct standard_palette_entry /* pngvalid format palette! */ -{ - png_byte red; - png_byte green; - png_byte blue; - png_byte alpha; -} standard_palette[256]; - typedef struct standard_display { png_store* ps; /* Test parameters (passed to the function) */ @@ -2730,14 +3306,16 @@ typedef struct standard_display png_uint_32 bit_width; /* Width of output row in bits */ size_t cbRow; /* Bytes in a row of the output image */ int do_interlace; /* Do interlacing internally */ - int is_transparent; /* Transparecy information was present. */ + int is_transparent; /* Transparency information was present. */ + int speed; /* Doing a speed test */ struct { png_uint_16 red; png_uint_16 green; png_uint_16 blue; } transparent; /* The transparent color, if set. */ - standard_palette + int npalette; /* Number of entries in the palette. */ + store_palette palette; } standard_display; @@ -2748,8 +3326,11 @@ standard_display_init(standard_display *dp, png_store* ps, png_uint_32 id, dp->ps = ps; dp->colour_type = COL_FROM_ID(id); dp->bit_depth = DEPTH_FROM_ID(id); - dp->alpha_sBIT = dp->blue_sBIT = dp->green_sBIT = dp->alpha_sBIT = - dp->bit_depth; + if (dp->colour_type == 3) + dp->red_sBIT = dp->blue_sBIT = dp->green_sBIT = dp->alpha_sBIT = 8; + else + dp->red_sBIT = dp->blue_sBIT = dp->green_sBIT = dp->alpha_sBIT = + dp->bit_depth; dp->interlace_type = INTERLACE_FROM_ID(id); dp->id = id; /* All the rest are filled in after the read_info: */ @@ -2761,48 +3342,98 @@ standard_display_init(standard_display *dp, png_store* ps, png_uint_32 id, dp->cbRow = 0; dp->do_interlace = do_interlace; dp->is_transparent = 0; + dp->speed = ps->speed; + dp->npalette = 0; /* Preset the transparent color to black: */ memset(&dp->transparent, 0, sizeof dp->transparent); /* Preset the palette to full intensity/opaque througout: */ memset(dp->palette, 0xff, sizeof dp->palette); +} +/* Initialize the palette fields - this must be done later because the palette + * comes from the particular png_store_file that is selected. + */ +static void +standard_palette_init(standard_display *dp) +{ + store_palette_entry *palette = store_current_palette(dp->ps, &dp->npalette); + + /* The remaining entries remain white/opaque. */ + if (dp->npalette > 0) + { + int i = dp->npalette; + memcpy(dp->palette, palette, i * sizeof *palette); + + /* Check for a non-opaque palette entry: */ + while (--i >= 0) + if (palette[i].alpha < 255) + break; + +# ifdef __GNUC__ + /* GCC can't handle the more obviously optimizable version. */ + if (i >= 0) + dp->is_transparent = 1; + else + dp->is_transparent = 0; +# else + dp->is_transparent = (i >= 0); +# endif + } } -/* Call this only if the colour type is 3 - PNG_COLOR_TYPE_PALETTE - otherwise - * it will png_error out. The API returns true if tRNS information was - * present. +/* Utility to read the palette from the PNG file and convert it into + * store_palette format. This returns 1 if there is any transparency in the + * palette (it does not check for a transparent colour in the non-palette case.) */ static int -standard_palette_init(standard_palette palette, png_structp pp, png_infop pi) +read_palette(store_palette palette, int *npalette, png_structp pp, png_infop pi) { png_colorp pal; png_bytep trans_alpha; int num; pal = 0; - num = -1; - if (png_get_PLTE(pp, pi, &pal, &num) & PNG_INFO_PLTE) + *npalette = -1; + + if (png_get_PLTE(pp, pi, &pal, npalette) & PNG_INFO_PLTE) { - int i; + int i = *npalette; - for (i=0; i<num; ++i) + if (i <= 0 || i > 256) + png_error(pp, "validate: invalid PLTE count"); + + while (--i >= 0) { palette[i].red = pal[i].red; palette[i].green = pal[i].green; palette[i].blue = pal[i].blue; } - /* Mark the remainder of the entries with a flag value: */ - for (; i<256; ++i) - palette[i].red = palette[i].green = palette[i].blue = 126; + /* Mark the remainder of the entries with a flag value (other than + * white/opaque which is the flag value stored above.) + */ + memset(palette + *npalette, 126, (256-*npalette) * sizeof *palette); } else /* !png_get_PLTE */ - png_error(pp, "validate: missing PLTE with color type 3"); + { + if (*npalette != (-1)) + png_error(pp, "validate: invalid PLTE result"); + /* But there is no palette, so record this: */ + *npalette = 0; + memset(palette, 113, sizeof palette); + } trans_alpha = 0; - num = -1; - if (png_get_tRNS(pp, pi, &trans_alpha, &num, 0) & PNG_INFO_tRNS) + num = 2; /* force error below */ + if ((png_get_tRNS(pp, pi, &trans_alpha, &num, 0) & PNG_INFO_tRNS) != 0 && + (trans_alpha != NULL || num != 1/*returns 1 for a transparent color*/) && + /* Oops, if a palette tRNS gets expanded png_read_update_info (at least so + * far as 1.5.4) does not zap the trans_alpha pointer, only num_trans, so + * in the above call we get a success, we get a pointer (who knows what + * to) and we get num_trans == 0: + */ + !(trans_alpha != NULL && num == 0)) /* TODO: fix this in libpng. */ { int i; @@ -2812,30 +3443,72 @@ standard_palette_init(standard_palette palette, png_structp pp, png_infop pi) * actually been filled in! Note that if the app were to pass the * last, png_color_16p, variable too it couldn't rely on this. */ - if (trans_alpha == 0 || num <= 0 || num > 256) + if (trans_alpha == NULL || num <= 0 || num > 256 || num > *npalette) png_error(pp, "validate: unexpected png_get_tRNS (palette) result"); for (i=0; i<num; ++i) palette[i].alpha = trans_alpha[i]; - for (; i<256; ++i) + for (num=*npalette; i<num; ++i) palette[i].alpha = 255; + for (; i<256; ++i) + palette[i].alpha = 33; /* flag value */ + return 1; /* transparency */ } else { - /* No transparency - just set the alpha channel to opaque. */ + /* No palette transparency - just set the alpha channel to opaque. */ int i; - for (i=0; i<256; ++i) + for (i=0, num=*npalette; i<num; ++i) palette[i].alpha = 255; + for (; i<256; ++i) + palette[i].alpha = 55; /* flag value */ + return 0; /* no transparency */ } } +/* Utility to validate the palette if it should not have changed (the + * non-transform case). + */ +static void +standard_palette_validate(standard_display *dp, png_structp pp, png_infop pi) +{ + int npalette; + store_palette palette; + + if (read_palette(palette, &npalette, pp, pi) != dp->is_transparent) + png_error(pp, "validate: palette transparency changed"); + + if (npalette != dp->npalette) + { + size_t pos = 0; + char msg[64]; + + pos = safecat(msg, sizeof msg, pos, "validate: palette size changed: "); + pos = safecatn(msg, sizeof msg, pos, dp->npalette); + pos = safecat(msg, sizeof msg, pos, " -> "); + pos = safecatn(msg, sizeof msg, pos, npalette); + png_error(pp, msg); + } + + { + int i = npalette; /* npalette is aliased */ + + while (--i >= 0) + if (palette[i].red != dp->palette[i].red || + palette[i].green != dp->palette[i].green || + palette[i].blue != dp->palette[i].blue || + palette[i].alpha != dp->palette[i].alpha) + png_error(pp, "validate: PLTE or tRNS chunk changed"); + } +} + /* By passing a 'standard_display' the progressive callbacks can be used * directly by the sequential code, the functions suffixed "_imp" are the * implementations, the functions without the suffix are the callbacks. @@ -2935,23 +3608,15 @@ standard_info_part1(standard_display *dp, png_structp pp, png_infop pi) if (png_get_rowbytes(pp, pi) != standard_rowsize(pp, dp->id)) png_error(pp, "validate: row size changed"); - /* The palette is never read for non-palette images, even though it is valid - * - this could be changed. + /* Validate the colour type 3 palette (this can be present on other color + * types.) */ - if (dp->colour_type == 3) /* palette */ - { - int i; - - dp->is_transparent = standard_palette_init(dp->palette, pp, pi); - - /* And validate the result. */ - for (i=0; i<256; ++i) - if (dp->palette[i].red != i || dp->palette[i].green != i || - dp->palette[i].blue != i) - png_error(pp, "validate: color type 3 PLTE chunk changed"); - } + standard_palette_validate(dp, pp, pi); - /* In any case always check for a tranparent color: */ + /* In any case always check for a tranparent color (notice that the + * colour type 3 case must not give a successful return on the get_tRNS call + * with these arguments!) + */ { png_color_16p trans_color = 0; @@ -3020,7 +3685,7 @@ standard_info_part2(standard_display *dp, png_structp pp, png_infop pi, png_error(pp, "bad png_get_rowbytes calculation"); /* Then ensure there is enough space for the output image(s). */ - store_ensure_image(dp->ps, pp, nImages * dp->cbRow * dp->h); + store_ensure_image(dp->ps, pp, nImages, dp->cbRow, dp->h); } static void @@ -3072,13 +3737,24 @@ progressive_row(png_structp pp, png_bytep new_row, png_uint_32 y, int pass) * us the y in the sub-image: */ if (dp->do_interlace && dp->interlace_type == PNG_INTERLACE_ADAM7) + { +#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED + /* Use this opportunity to validate the png 'current' APIs: */ + if (y != png_get_current_row_number(pp)) + png_error(pp, "png_get_current_row_number is broken"); + + if (pass != png_get_current_pass_number(pp)) + png_error(pp, "png_get_current_pass_number is broken"); +#endif + y = PNG_ROW_FROM_PASS_ROW(y, pass); + } /* Validate this just in case. */ if (y >= dp->h) png_error(pp, "invalid y to progressive row callback"); - row = dp->ps->image + y * dp->cbRow; + row = store_image_row(dp->ps, pp, 0, y); /* Combine the new row into the old: */ if (dp->do_interlace) @@ -3098,22 +3774,20 @@ progressive_row(png_structp pp, png_bytep new_row, png_uint_32 y, int pass) static void sequential_row(standard_display *dp, png_structp pp, png_infop pi, - PNG_CONST png_bytep pImage, PNG_CONST png_bytep pDisplay) + PNG_CONST int iImage, PNG_CONST int iDisplay) { PNG_CONST int npasses = dp->npasses; PNG_CONST int do_interlace = dp->do_interlace && dp->interlace_type == PNG_INTERLACE_ADAM7; PNG_CONST png_uint_32 height = standard_height(pp, dp->id); PNG_CONST png_uint_32 width = standard_width(pp, dp->id); - PNG_CONST size_t cbRow = dp->cbRow; + PNG_CONST png_store* ps = dp->ps; int pass; for (pass=0; pass<npasses; ++pass) { png_uint_32 y; png_uint_32 wPass = PNG_PASS_COLS(width, pass); - png_bytep pRow1 = pImage; - png_bytep pRow2 = pDisplay; for (y=0; y<height; ++y) { @@ -3138,21 +3812,19 @@ sequential_row(standard_display *dp, png_structp pp, png_infop pi, png_read_row(pp, row, display); - if (pRow1 != NULL) - deinterlace_row(pRow1, row, dp->pixel_size, dp->w, pass); + if (iImage >= 0) + deinterlace_row(store_image_row(ps, pp, iImage, y), row, + dp->pixel_size, dp->w, pass); - if (pRow2 != NULL) - deinterlace_row(pRow2, display, dp->pixel_size, dp->w, pass); + if (iDisplay >= 0) + deinterlace_row(store_image_row(ps, pp, iDisplay, y), display, + dp->pixel_size, dp->w, pass); } } else - png_read_row(pp, pRow1, pRow2); - - if (pRow1 != NULL) - pRow1 += cbRow; - - if (pRow2 != NULL) - pRow2 += cbRow; + png_read_row(pp, + iImage >= 0 ? store_image_row(ps, pp, iImage, y) : NULL, + iDisplay >= 0 ? store_image_row(ps, pp, iDisplay, y) : NULL); } } @@ -3163,8 +3835,8 @@ sequential_row(standard_display *dp, png_structp pp, png_infop pi, } static void -standard_row_validate(standard_display *dp, png_structp pp, png_const_bytep row, - png_const_bytep display, png_uint_32 y) +standard_row_validate(standard_display *dp, png_structp pp, + int iImage, int iDisplay, png_uint_32 y) { png_byte std[STANDARD_ROWMAX]; @@ -3182,7 +3854,8 @@ standard_row_validate(standard_display *dp, png_structp pp, png_const_bytep row, * row bytes are always trashed, so we always do a pixel_cmp here even though * a memcmp of all cbRow bytes will succeed for the sequential reader. */ - if (row != NULL && pixel_cmp(std, row, dp->bit_width) != 0) + if (iImage >= 0 && pixel_cmp(std, store_image_row(dp->ps, pp, iImage, y), + dp->bit_width) != 0) { char msg[64]; sprintf(msg, "PNG image row %d changed", y); @@ -3193,7 +3866,8 @@ standard_row_validate(standard_display *dp, png_structp pp, png_const_bytep row, * byte at the end of the row if the row is not an exact multiple * of 8 bits wide. */ - if (display != NULL && pixel_cmp(std, display, dp->bit_width) != 0) + if (iDisplay >= 0 && pixel_cmp(std, store_image_row(dp->ps, pp, iDisplay, y), + dp->bit_width) != 0) { char msg[64]; sprintf(msg, "display row %d changed", y); @@ -3202,21 +3876,19 @@ standard_row_validate(standard_display *dp, png_structp pp, png_const_bytep row, } static void -standard_image_validate(standard_display *dp, png_structp pp, - png_const_bytep pImage, png_const_bytep pDisplay) +standard_image_validate(standard_display *dp, png_structp pp, int iImage, + int iDisplay) { png_uint_32 y; - for (y=0; y<dp->h; ++y) - { - standard_row_validate(dp, pp, pImage, pDisplay, y); + if (iImage >= 0) + store_image_check(dp->ps, pp, iImage); - if (pImage != NULL) - pImage += dp->cbRow; + if (iDisplay >= 0) + store_image_check(dp->ps, pp, iDisplay); - if (pDisplay != NULL) - pDisplay += dp->cbRow; - } + for (y=0; y<dp->h; ++y) + standard_row_validate(dp, pp, iImage, iDisplay, y); /* This avoids false positives if the validation code is never called! */ dp->ps->validated = 1; @@ -3232,7 +3904,7 @@ standard_end(png_structp pp, png_infop pi) /* Validate the image - progressive reading only produces one variant for * interlaced images. */ - standard_image_validate(dp, pp, dp->ps->image, NULL); + standard_image_validate(dp, pp, 0, -1); } /* A single test run checking the standard image to ensure it is not damaged. */ @@ -3265,6 +3937,9 @@ standard_test(png_store* PNG_CONST psIn, png_uint_32 PNG_CONST id, "pngvalid sequential deinterlacer") : (d.ps->progressive ? "progressive reader" : "sequential reader")); + /* Initialize the palette correctly from the png_store_file. */ + standard_palette_init(&d); + /* Introduce the correct read function. */ if (d.ps->progressive) { @@ -3292,15 +3967,13 @@ standard_test(png_store* PNG_CONST psIn, png_uint_32 PNG_CONST id, * values. */ { - PNG_CONST png_bytep pImage = d.ps->image; - PNG_CONST png_bytep pDisplay = pImage + d.cbRow * d.h; - - sequential_row(&d, pp, pi, pImage, pDisplay); + sequential_row(&d, pp, pi, 0, 1); /* After the last pass loop over the rows again to check that the * image is correct. */ - standard_image_validate(&d, pp, pImage, pDisplay); + if (!d.speed) + standard_image_validate(&d, pp, 0, 1); } } @@ -3329,7 +4002,7 @@ test_standard(png_modifier* PNG_CONST pm, png_byte PNG_CONST colour_type, for (interlace_type = PNG_INTERLACE_NONE; interlace_type < PNG_INTERLACE_LAST; ++interlace_type) { - standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), + standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/, interlace_type, 0, 0, 0), 0/*do_interlace*/); if (fail(pm)) @@ -3388,25 +4061,25 @@ test_size(png_modifier* PNG_CONST pm, png_byte PNG_CONST colour_type, * validates the write side of libpng. There are four possibilities * to validate. */ - standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), + standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/, PNG_INTERLACE_NONE, w, h, 0), 0/*do_interlace*/); if (fail(pm)) return 0; - standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), + standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/, PNG_INTERLACE_NONE, w, h, 1), 0/*do_interlace*/); if (fail(pm)) return 0; - standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), + standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/, PNG_INTERLACE_ADAM7, w, h, 0), 0/*do_interlace*/); if (fail(pm)) return 0; - standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), + standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/, PNG_INTERLACE_ADAM7, w, h, 1), 0/*do_interlace*/); if (fail(pm)) @@ -3416,13 +4089,13 @@ test_size(png_modifier* PNG_CONST pm, png_byte PNG_CONST colour_type, * in the progressive case this does actually make a difference * to the code used in the non-interlaced case too. */ - standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), + standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/, PNG_INTERLACE_NONE, w, h, 0), 1/*do_interlace*/); if (fail(pm)) return 0; - standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), + standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/, PNG_INTERLACE_ADAM7, w, h, 0), 1/*do_interlace*/); if (fail(pm)) @@ -3462,6 +4135,7 @@ perform_size_test(png_modifier *pm) /******************************* TRANSFORM TESTS ******************************/ +#ifdef PNG_READ_TRANSFORMS_SUPPORTED /* A set of tests to validate libpng image transforms. The possibilities here * are legion because the transforms can be combined in a combinatorial * fashion. To deal with this some measure of restraint is required, otherwise @@ -3524,7 +4198,7 @@ image_pixel_setf(image_pixel *this, unsigned int max) */ static void image_pixel_init(image_pixel *this, png_const_bytep row, png_byte colour_type, - png_byte bit_depth, png_uint_32 x, standard_palette palette) + png_byte bit_depth, png_uint_32 x, store_palette palette) { PNG_CONST png_byte sample_depth = (png_byte)(colour_type == PNG_COLOR_TYPE_PALETTE ? 8 : bit_depth); @@ -3585,44 +4259,33 @@ image_pixel_init(image_pixel *this, png_const_bytep row, png_byte colour_type, } /* Convert a palette image to an rgb image. This necessarily converts the tRNS - * chunk at the same time, because the tRNS will be in palette form. + * chunk at the same time, because the tRNS will be in palette form. The way + * palette validation works means that the original palette is never updated, + * instead the image_pixel value from the row contains the RGB of the + * corresponding palette entry and *this* is updated. Consequently this routine + * only needs to change the colour type information. */ static void -image_pixel_convert_PLTE(image_pixel *this, const standard_display *display) +image_pixel_convert_PLTE(image_pixel *this) { if (this->colour_type == PNG_COLOR_TYPE_PALETTE) { - PNG_CONST unsigned int i = this->palette_index; - - this->bit_depth = this->sample_depth; - this->red = display->palette[i].red; - this->green = display->palette[i].green; - this->blue = display->palette[i].blue; - this->red_sBIT = display->red_sBIT; - this->green_sBIT = display->green_sBIT; - this->blue_sBIT = display->blue_sBIT; - if (this->have_tRNS) { - this->alpha = display->palette[i].alpha; this->colour_type = PNG_COLOR_TYPE_RGB_ALPHA; this->have_tRNS = 0; } else - { - this->alpha = 255; this->colour_type = PNG_COLOR_TYPE_RGB; - } - this->alpha_sBIT = 8; - /* And regenerate the scaled values and all the errors, which are now set - * back to the initial values. + /* The bit depth of the row changes at this point too (notice that this is + * the row format, not the sample depth, which is separate.) */ - image_pixel_setf(this, 255); + this->bit_depth = 8; } } -/* Add an alpha channel, this will glom in the tRNS information because tRNS is +/* Add an alpha channel; this will import the tRNS information because tRNS is * not valid in an alpha image. The bit depth will invariably be set to at * least 8. Palette images will be converted to alpha (using the above API). */ @@ -3630,7 +4293,7 @@ static void image_pixel_add_alpha(image_pixel *this, const standard_display *display) { if (this->colour_type == PNG_COLOR_TYPE_PALETTE) - image_pixel_convert_PLTE(this, display); + image_pixel_convert_PLTE(this); if ((this->colour_type & PNG_COLOR_MASK_ALPHA) == 0) { @@ -3748,6 +4411,10 @@ typedef struct transform_display /* Local variables */ png_byte output_colour_type; png_byte output_bit_depth; + + /* Variables for the individual transforms. */ + /* png_set_background */ + image_pixel background_colour; } transform_display; /* Two functions to end the list: */ @@ -3996,17 +4663,19 @@ transform_info(png_structp pp, png_infop pi) static void transform_range_check(png_structp pp, unsigned int r, unsigned int g, unsigned int b, unsigned int a, unsigned int in_digitized, double in, - unsigned int out, png_byte sample_depth, double err, PNG_CONST char *name) + unsigned int out, png_byte sample_depth, double err, PNG_CONST char *name, + double digitization_error) { /* Compare the scaled, digitzed, values of our local calculation (in+-err) * with the digitized values libpng produced; 'sample_depth' is the actual * digitization depth of the libpng output colors (the bit depth except for - * palette images where it is always 8.) + * palette images where it is always 8.) The check on 'err' is to detect + * internal errors in pngvalid itself (the threshold is about 1/255.) */ unsigned int max = (1U<<sample_depth)-1; - double in_min = ceil((in-err)*max - .5); - double in_max = floor((in+err)*max + .5); - if (!(out >= in_min && out <= in_max)) + double in_min = ceil((in-err)*max - digitization_error); + double in_max = floor((in+err)*max + digitization_error); + if (err > 4E-3 || !(out >= in_min && out <= in_max)) { char message[256]; size_t pos; @@ -4035,15 +4704,14 @@ transform_range_check(png_structp pp, unsigned int r, unsigned int g, } static void -transform_image_validate(transform_display *dp, png_structp pp, png_infop pi, - png_const_bytep pRow) +transform_image_validate(transform_display *dp, png_structp pp, png_infop pi) { /* Constants for the loop below: */ + PNG_CONST png_store* PNG_CONST ps = dp->this.ps; PNG_CONST png_byte in_ct = dp->this.colour_type; PNG_CONST png_byte in_bd = dp->this.bit_depth; PNG_CONST png_uint_32 w = dp->this.w; PNG_CONST png_uint_32 h = dp->this.h; - PNG_CONST size_t cbRow = dp->this.cbRow; PNG_CONST png_byte out_ct = dp->output_colour_type; PNG_CONST png_byte out_bd = dp->output_bit_depth; PNG_CONST png_byte sample_depth = (png_byte)(out_ct == @@ -4053,22 +4721,63 @@ transform_image_validate(transform_display *dp, png_structp pp, png_infop pi, PNG_CONST png_byte blue_sBIT = dp->this.blue_sBIT; PNG_CONST png_byte alpha_sBIT = dp->this.alpha_sBIT; PNG_CONST int have_tRNS = dp->this.is_transparent; + double digitization_error; - standard_palette out_palette; + store_palette out_palette; png_uint_32 y; UNUSED(pi) + /* Check for row overwrite errors */ + store_image_check(dp->this.ps, pp, 0); + /* Read the palette corresponding to the output if the output colour type * indicates a palette, othewise set out_palette to garbage. */ if (out_ct == PNG_COLOR_TYPE_PALETTE) - (void)standard_palette_init(out_palette, pp, pi); + { + /* Validate that the palette count itself has not changed - this is not + * expected. + */ + int npalette = (-1); + + (void)read_palette(out_palette, &npalette, pp, pi); + if (npalette != dp->this.npalette) + png_error(pp, "unexpected change in palette size"); + + digitization_error = .5; + } else + { + png_byte in_sample_depth; + memset(out_palette, 0x5e, sizeof out_palette); - for (y=0; y<h; ++y, pRow += cbRow) + /* assume-8-bit-calculations means assume that if the input has 8 bit + * (or less) samples and the output has 16 bit samples the calculations + * will be done with 8 bit precision, not 16. + * + * TODO: fix this in libpng; png_set_expand_16 should cause 16 bit + * calculations to be used throughout. + */ + if (in_ct == PNG_COLOR_TYPE_PALETTE || in_bd < 16) + in_sample_depth = 8; + else + in_sample_depth = in_bd; + + if (sample_depth != 16 || in_sample_depth > 8 || + !dp->pm->calculations_use_input_precision) + digitization_error = .5; + + /* Else errors are at 8 bit precision, scale .5 in 8 bits to the 16 bits: + */ + else + digitization_error = .5 * 257; + } + + for (y=0; y<h; ++y) { + png_const_bytep PNG_CONST pRow = store_image_row(ps, pp, 0, y); png_uint_32 x; /* The original, standard, row pre-transforms. */ @@ -4121,24 +4830,26 @@ transform_image_validate(transform_display *dp, png_structp pp, png_infop pi, */ if (in_pixel.red != out_pixel.red) transform_range_check(pp, r, g, b, a, in_pixel.red, in_pixel.redf, - out_pixel.red, sample_depth, in_pixel.rede, "red/gray"); + out_pixel.red, sample_depth, in_pixel.rede, "red/gray", + digitization_error); if ((out_ct & PNG_COLOR_MASK_COLOR) != 0 && in_pixel.green != out_pixel.green) transform_range_check(pp, r, g, b, a, in_pixel.green, in_pixel.greenf, out_pixel.green, sample_depth, in_pixel.greene, - "green"); + "green", digitization_error); if ((out_ct & PNG_COLOR_MASK_COLOR) != 0 && in_pixel.blue != out_pixel.blue) transform_range_check(pp, r, g, b, a, in_pixel.blue, in_pixel.bluef, - out_pixel.blue, sample_depth, in_pixel.bluee, "blue"); + out_pixel.blue, sample_depth, in_pixel.bluee, "blue", + digitization_error); if ((out_ct & PNG_COLOR_MASK_ALPHA) != 0 && in_pixel.alpha != out_pixel.alpha) transform_range_check(pp, r, g, b, a, in_pixel.alpha, in_pixel.alphaf, out_pixel.alpha, sample_depth, in_pixel.alphae, - "alpha"); + "alpha", digitization_error); } /* pixel (x) loop */ } /* row (y) loop */ @@ -4151,7 +4862,7 @@ transform_end(png_structp pp, png_infop pi) { transform_display *dp = png_get_progressive_ptr(pp); - transform_image_validate(dp, pp, pi, dp->this.ps->image); + transform_image_validate(dp, pp, pi); } /* A single test run. */ @@ -4169,8 +4880,9 @@ transform_test(png_modifier *pmIn, PNG_CONST png_uint_32 idIn, png_structp pp; png_infop pi; - /* Get a png_struct for writing the image. */ + /* Get a png_struct for reading the image. */ pp = set_modifier_for_read(d.pm, &pi, d.this.id, name); + standard_palette_init(&d.this); # if 0 /* Logging (debugging only) */ @@ -4205,9 +4917,10 @@ transform_test(png_modifier *pmIn, PNG_CONST png_uint_32 idIn, /* Process the 'info' requirements. Only one image is generated */ transform_info_imp(&d, pp, pi); - sequential_row(&d.this, pp, pi, NULL, d.this.ps->image); + sequential_row(&d.this, pp, pi, -1, 0); - transform_image_validate(&d, pp, pi, d.this.ps->image); + if (!d.this.speed) + transform_image_validate(&d, pp, pi); } modifier_reset(d.pm); @@ -4219,12 +4932,12 @@ transform_test(png_modifier *pmIn, PNG_CONST png_uint_32 idIn, /* The transforms: */ #define ITSTRUCT(name) image_transform_##name -#define IT(name,prev)\ +#define IT(name)\ static image_transform ITSTRUCT(name) =\ {\ #name,\ 1, /*enable*/\ - &ITSTRUCT(prev), /*list*/\ + &PT, /*list*/\ 0, /*global_use*/\ 0, /*local_use*/\ 0, /*next*/\ @@ -4232,6 +4945,7 @@ static image_transform ITSTRUCT(name) =\ image_transform_png_set_##name##_mod,\ image_transform_png_set_##name##_add\ } +#define PT ITSTRUCT(end) /* stores the previous transform */ /* To save code: */ static int @@ -4247,6 +4961,7 @@ image_transform_default_add(image_transform *this, return 1; } +#ifdef PNG_READ_EXPAND_SUPPORTED /* png_set_palette_to_rgb */ static void image_transform_png_set_palette_to_rgb_set(PNG_CONST image_transform *this, @@ -4261,7 +4976,7 @@ image_transform_png_set_palette_to_rgb_mod(PNG_CONST image_transform *this, image_pixel *that, png_structp pp, PNG_CONST transform_display *display) { if (that->colour_type == PNG_COLOR_TYPE_PALETTE) - image_pixel_convert_PLTE(that, &display->this); + image_pixel_convert_PLTE(that); this->next->mod(this->next, that, pp, display); } @@ -4278,9 +4993,12 @@ image_transform_png_set_palette_to_rgb_add(image_transform *this, return colour_type == PNG_COLOR_TYPE_PALETTE; } -IT(palette_to_rgb, end); - +IT(palette_to_rgb); +#undef PT +#define PT ITSTRUCT(palette_to_rgb) +#endif /* PNG_READ_EXPAND_SUPPORTED */ +#ifdef PNG_READ_EXPAND_SUPPORTED /* png_set_tRNS_to_alpha */ static void image_transform_png_set_tRNS_to_alpha_set(PNG_CONST image_transform *this, @@ -4296,10 +5014,10 @@ image_transform_png_set_tRNS_to_alpha_mod(PNG_CONST image_transform *this, { /* LIBPNG BUG: this always forces palette images to RGB. */ if (that->colour_type == PNG_COLOR_TYPE_PALETTE) - image_pixel_convert_PLTE(that, &display->this); + image_pixel_convert_PLTE(that); /* This effectively does an 'expand' only if there is some transparency to - * covert to an alpha channel. + * convert to an alpha channel. */ if (that->have_tRNS) image_pixel_add_alpha(that, &display->this); @@ -4332,8 +5050,12 @@ image_transform_png_set_tRNS_to_alpha_add(image_transform *this, return (colour_type & PNG_COLOR_MASK_ALPHA) == 0; } -IT(tRNS_to_alpha,palette_to_rgb); +IT(tRNS_to_alpha); +#undef PT +#define PT ITSTRUCT(tRNS_to_alpha) +#endif /* PNG_READ_EXPAND_SUPPORTED */ +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED /* png_set_gray_to_rgb */ static void image_transform_png_set_gray_to_rgb_set(PNG_CONST image_transform *this, @@ -4386,8 +5108,12 @@ image_transform_png_set_gray_to_rgb_add(image_transform *this, return (colour_type & PNG_COLOR_MASK_COLOR) == 0; } -IT(gray_to_rgb,tRNS_to_alpha); +IT(gray_to_rgb); +#undef PT +#define PT ITSTRUCT(gray_to_rgb) +#endif /* PNG_READ_GRAY_TO_RGB_SUPPORTED */ +#ifdef PNG_READ_EXPAND_SUPPORTED /* png_set_expand */ static void image_transform_png_set_expand_set(PNG_CONST image_transform *this, @@ -4403,7 +5129,7 @@ image_transform_png_set_expand_mod(PNG_CONST image_transform *this, { /* The general expand case depends on what the colour type is: */ if (that->colour_type == PNG_COLOR_TYPE_PALETTE) - image_pixel_convert_PLTE(that, &display->this); + image_pixel_convert_PLTE(that); else if (that->bit_depth < 8) /* grayscale */ that->sample_depth = that->bit_depth = 8; @@ -4428,8 +5154,12 @@ image_transform_png_set_expand_add(image_transform *this, return (colour_type & PNG_COLOR_MASK_ALPHA) == 0; } -IT(expand,gray_to_rgb); +IT(expand); +#undef PT +#define PT ITSTRUCT(expand) +#endif /* PNG_READ_EXPAND_SUPPORTED */ +#ifdef PNG_READ_EXPAND_SUPPORTED /* png_set_expand_gray_1_2_4_to_8 * LIBPNG BUG: this just does an 'expand' */ @@ -4458,8 +5188,102 @@ image_transform_png_set_expand_gray_1_2_4_to_8_add(image_transform *this, bit_depth); } -IT(expand_gray_1_2_4_to_8, expand); +IT(expand_gray_1_2_4_to_8); +#undef PT +#define PT ITSTRUCT(expand_gray_1_2_4_to_8) +#endif /* PNG_READ_EXPAND_SUPPORTED */ + +#ifdef PNG_READ_EXPAND_16_SUPPORTED +/* png_set_expand_16 */ +static void +image_transform_png_set_expand_16_set(PNG_CONST image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_set_expand_16(pp); + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_expand_16_mod(PNG_CONST image_transform *this, + image_pixel *that, png_structp pp, PNG_CONST transform_display *display) +{ + /* Expect expand_16 to expand everything to 16 bits as a result of also + * causing 'expand' to happen. + */ + if (that->colour_type == PNG_COLOR_TYPE_PALETTE) + image_pixel_convert_PLTE(that); + + if (that->have_tRNS) + image_pixel_add_alpha(that, &display->this); + + if (that->bit_depth < 16) + that->sample_depth = that->bit_depth = 16; + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_expand_16_add(image_transform *this, + PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(colour_type) + + this->next = *that; + *that = this; + + /* expand_16 does something unless the bit depth is already 16. */ + return bit_depth < 16; +} + +IT(expand_16); +#undef PT +#define PT ITSTRUCT(expand_16) +#endif /* PNG_READ_EXPAND_16_SUPPORTED */ + +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED /* API added in 1.5.4 */ +/* png_set_scale_16 */ +static void +image_transform_png_set_scale_16_set(PNG_CONST image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_set_scale_16(pp); + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_scale_16_mod(PNG_CONST image_transform *this, + image_pixel *that, png_structp pp, PNG_CONST transform_display *display) +{ + if (that->bit_depth == 16) + { + that->sample_depth = that->bit_depth = 8; + if (that->red_sBIT > 8) that->red_sBIT = 8; + if (that->green_sBIT > 8) that->green_sBIT = 8; + if (that->blue_sBIT > 8) that->blue_sBIT = 8; + if (that->alpha_sBIT > 8) that->alpha_sBIT = 8; + } + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_scale_16_add(image_transform *this, + PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(colour_type) + + this->next = *that; + *that = this; + + return bit_depth > 8; +} + +IT(scale_16); +#undef PT +#define PT ITSTRUCT(scale_16) +#endif /* PNG_READ_SCALE_16_TO_8_SUPPORTED (1.5.4 on) */ +#ifdef PNG_READ_16_TO_8_SUPPORTED /* the default before 1.5.4 */ /* png_set_strip_16 */ static void image_transform_png_set_strip_16_set(PNG_CONST image_transform *this, @@ -4481,9 +5305,19 @@ image_transform_png_set_strip_16_mod(PNG_CONST image_transform *this, if (that->blue_sBIT > 8) that->blue_sBIT = 8; if (that->alpha_sBIT > 8) that->alpha_sBIT = 8; -# ifndef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED - /* The strip 16 algoirithm drops the low 8 bits rather than calculating + /* Prior to 1.5.4 png_set_strip_16 would use an 'accurate' method if this + * configuration option is set. From 1.5.4 the flag is never set and the + * 'scale' API (above) must be used. + */ +# ifdef PNG_READ_ACCURATE_SCALE_SUPPORTED +# if PNG_LIBPNG_VER >= 10504 +# error PNG_READ_ACCURATE_SCALE should not be set +# endif + + /* The strip 16 algorithm drops the low 8 bits rather than calculating * 1/257, so we need to adjust the permitted errors appropriately: + * Notice that this is only relevant prior to the addition of the + * png_set_scale_16 API in 1.5.4 (but 1.5.4+ always defines the above!) */ { PNG_CONST double d = (255-128.5)/65535; @@ -4510,8 +5344,12 @@ image_transform_png_set_strip_16_add(image_transform *this, return bit_depth > 8; } -IT(strip_16, expand_gray_1_2_4_to_8); +IT(strip_16); +#undef PT +#define PT ITSTRUCT(strip_16) +#endif /* PNG_READ_16_TO_8_SUPPORTED */ +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED /* png_set_strip_alpha */ static void image_transform_png_set_strip_alpha_set(PNG_CONST image_transform *this, @@ -4532,7 +5370,6 @@ image_transform_png_set_strip_alpha_mod(PNG_CONST image_transform *this, that->have_tRNS = 0; that->alphaf = 1; - that->alphae = 0; this->next->mod(this->next, that, pp, display); } @@ -4549,8 +5386,12 @@ image_transform_png_set_strip_alpha_add(image_transform *this, return (colour_type & PNG_COLOR_MASK_ALPHA) != 0; } -IT(strip_alpha,strip_16); +IT(strip_alpha); +#undef PT +#define PT ITSTRUCT(strip_alpha) +#endif /* PNG_READ_STRIP_ALPHA_SUPPORTED */ +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED /* png_set_rgb_to_gray(png_structp, int err_action, double red, double green) * png_set_rgb_to_gray_fixed(png_structp, int err_action, png_fixed_point red, * png_fixed_point green) @@ -4588,7 +5429,7 @@ image_transform_png_set_rgb_to_gray_mod(PNG_CONST image_transform *this, if ((that->colour_type & PNG_COLOR_MASK_COLOR) != 0) { if (that->colour_type == PNG_COLOR_TYPE_PALETTE) - image_pixel_convert_PLTE(that, &display->this); + image_pixel_convert_PLTE(that); /* Image now has RGB channels... */ that->bluef = that->greenf = that->redf = (that->redf * 6968 + @@ -4626,8 +5467,12 @@ image_transform_png_set_rgb_to_gray_add(image_transform *this, return (colour_type & PNG_COLOR_MASK_COLOR) != 0; } -IT(rgb_to_gray,strip_alpha); +IT(rgb_to_gray); +#undef PT +#define PT ITSTRUCT(rgb_to_gray) +#endif /* PNG_READ_RGB_TO_GRAY_SUPPORTED */ +#ifdef PNG_READ_BACKGROUND_SUPPORTED /* png_set_background(png_structp, png_const_color_16p background_color, * int background_gamma_code, int need_expand, double background_gamma) * png_set_background_fixed(png_structp, png_const_color_16p background_color, @@ -4640,19 +5485,54 @@ static void image_transform_png_set_background_set(PNG_CONST image_transform *this, transform_display *that, png_structp pp, png_infop pi) { + png_byte colour_type, bit_depth; + png_byte random_bytes[8]; /* 8 bytes - 64 bits - the biggest pixel */ png_color_16 back; - /* Since we don't know the output bit depth at this point we must use the - * input values and ask libpng to expand the chunk as required. + /* We need a background colour, because we don't know exactly what transforms + * have been set we have to supply the colour in the original file format and + * so we need to know what that is! The background colour is stored in the + * transform_display. + */ + RANDOMIZE(random_bytes); + + /* Read the random value, for colour type 3 the background colour is actually + * expressed as a 24bit rgb, not an index. */ - back.index = 255; /* Should not be used */ - back.gray = back.blue = back.green = back.red = - (png_uint_16)((1U << that->this.bit_depth) >> 1); + colour_type = that->this.colour_type; + if (colour_type == 3) + { + colour_type = PNG_COLOR_TYPE_RGB; + bit_depth = 8; + } + + else + bit_depth = that->this.bit_depth; + + image_pixel_init(&that->background_colour, random_bytes, colour_type, + bit_depth, 0/*x*/, 0/*unused: palette*/); + + /* Extract the background colour from this image_pixel, but make sure the + * unused fields of 'back' are garbage. + */ + RANDOMIZE(back); + + if (colour_type & PNG_COLOR_MASK_COLOR) + { + back.red = (png_uint_16)that->background_colour.red; + back.green = (png_uint_16)that->background_colour.green; + back.blue = (png_uint_16)that->background_colour.blue; + } + + else + back.gray = (png_uint_16)that->background_colour.red; # ifdef PNG_FLOATING_POINT_SUPPORTED - png_set_background(pp, &back, PNG_BACKGROUND_GAMMA_FILE, 1, 0); + png_set_background(pp, &back, PNG_BACKGROUND_GAMMA_FILE, 1/*need expand*/, + 0); # else - png_set_background_fixed(pp, &back, PNG_BACKGROUND_GAMMA_FILE, 1, 0); + png_set_background_fixed(pp, &back, PNG_BACKGROUND_GAMMA_FILE, + 1/*need expand*/, 0); # endif this->next->set(this->next, that, pp, pi); @@ -4669,32 +5549,40 @@ image_transform_png_set_background_mod(PNG_CONST image_transform *this, /* This is only necessary if the alpha value is less than 1. */ if (that->alphaf < 1) { - /* Repeat the calculation above and scale the result: */ - unsigned int tmp = (1U << display->this.bit_depth); - double component = (tmp >> 1)/(double)(tmp-1); + PNG_CONST image_pixel *back = &display->background_colour; /* Now we do the background calculation without any gamma correction. */ if (that->alphaf <= 0) { - that->bluef = that->greenf = that->redf = component; - that->bluee = that->greene = that->rede = component * DBL_EPSILON; - that->blue_sBIT = that->green_sBIT = that->red_sBIT = that->bit_depth; + that->redf = back->redf; + that->greenf = back->greenf; + that->bluef = back->bluef; + + that->rede = back->rede; + that->greene = back->greene; + that->bluee = back->bluee; + + that->red_sBIT= back->red_sBIT; + that->green_sBIT= back->green_sBIT; + that->blue_sBIT= back->blue_sBIT; } - else + else /* 0 < alpha < 1 */ { - component *= 1-that->alphaf; - that->redf = that->redf * that->alphaf + component; - that->rede = that->rede * that->alphaf + that->redf * 3 * DBL_EPSILON; - that->greenf = that->greenf * that->alphaf + component; - that->greene = that->greene * that->alphaf + that->greenf * 3 * + double alf = 1 - that->alphaf; + + that->redf = that->redf * that->alphaf + back->redf * alf; + that->rede = that->rede * that->alphaf + back->rede * alf + + DBL_EPSILON; + that->greenf = that->greenf * that->alphaf + back->greenf * alf; + that->greene = that->greene * that->alphaf + back->greene * alf + DBL_EPSILON; - that->bluef = that->bluef * that->alphaf + component; - that->bluee = that->bluee * that->alphaf + that->bluef * 3 * + that->bluef = that->bluef * that->alphaf + back->bluef * alf; + that->bluee = that->bluee * that->alphaf + back->bluee * alf + DBL_EPSILON; } - /* Remove the alpha type and set the alpha. */ + /* Remove the alpha type and set the alpha (not in that order.) */ that->alphaf = 1; that->alphae = 0; @@ -4702,6 +5590,7 @@ image_transform_png_set_background_mod(PNG_CONST image_transform *this, that->colour_type = PNG_COLOR_TYPE_RGB; else if (that->colour_type == PNG_COLOR_TYPE_GRAY_ALPHA) that->colour_type = PNG_COLOR_TYPE_GRAY; + /* PNG_COLOR_TYPE_PALETTE is not changed */ } this->next->mod(this->next, that, pp, display); @@ -4709,9 +5598,13 @@ image_transform_png_set_background_mod(PNG_CONST image_transform *this, #define image_transform_png_set_background_add image_transform_default_add -IT(background,rgb_to_gray); +IT(background); +#undef PT +#define PT ITSTRUCT(background) +#endif /* PNG_READ_BACKGROUND_SUPPORTED */ -static image_transform *PNG_CONST image_transform_first = &ITSTRUCT(background); +/* This may just be 'end' if all the transforms are disabled! */ +static image_transform *PNG_CONST image_transform_first = &PT; static void transform_enable(PNG_CONST char *name) @@ -4963,13 +5856,15 @@ IT(@); /* png_set_shift(png_structp, png_const_color_8p true_bits) */ /*NOTE: TBD NYI */ -static int -test_transform(png_modifier* PNG_CONST pm, png_byte PNG_CONST colour_type, - int bdlo, int PNG_CONST bdhi, png_uint_32 max) +static void +perform_transform_test(png_modifier *pm) { - for (; bdlo <= bdhi; ++bdlo) + png_byte colour_type = 0; + png_byte bit_depth = 0; + int palette_number = 0; + + while (next_format(&colour_type, &bit_depth, &palette_number)) { - PNG_CONST png_byte bit_depth = DEPTH(bdlo); png_uint_32 counter = 0; size_t base_pos; char name[64]; @@ -4981,48 +5876,28 @@ test_transform(png_modifier* PNG_CONST pm, png_byte PNG_CONST colour_type, size_t pos = base_pos; PNG_CONST image_transform *list = 0; - counter = image_transform_add(&list, max, counter, name, sizeof name, - &pos, colour_type, bit_depth); + /* 'max' is currently hardwired to '1'; this should be settable on the + * command line. + */ + counter = image_transform_add(&list, 1/*max*/, counter, + name, sizeof name, &pos, colour_type, bit_depth); if (counter == 0) break; /* The command line can change this to checking interlaced images. */ - transform_test(pm, FILEID(colour_type, bit_depth, pm->interlace_type, - 0, 0, 0), list, name); + transform_test(pm, FILEID(colour_type, bit_depth, palette_number, + pm->interlace_type, 0, 0, 0), list, name); if (fail(pm)) - return 0; + return; } } - - return 1; /* keep going */ -} - -static void -perform_transform_test(png_modifier *pm) -{ - /* Test each colour type over the valid range of bit depths (expressed as - * log2(bit_depth) in turn, stop as soon as any error is detected. - */ - if (!test_transform(pm, 0, 0, READ_BDHI, 1)) - return; - - if (!test_transform(pm, 2, 3, READ_BDHI, 1)) - return; - - if (!test_transform(pm, 3, 0, 3, 1)) - return; - - if (!test_transform(pm, 4, 3, READ_BDHI, 1)) - return; - - if (!test_transform(pm, 6, 3, READ_BDHI, 1)) - return; } - +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ /********************************* GAMMA TESTS ********************************/ +#ifdef PNG_READ_GAMMA_SUPPORTED /* Gamma test images. */ typedef struct gamma_modification { @@ -5175,12 +6050,14 @@ typedef struct gamma_display png_modifier* pm; double file_gamma; double screen_gamma; + double background_gamma; png_byte sbit; int threshold_test; - PNG_CONST char* name; - int speed; int use_input_precision; - int strip16; + int scale16; + int expand16; + int do_background; + png_color_16 background_color; /* Local variables */ double maxerrout; @@ -5188,10 +6065,14 @@ typedef struct gamma_display double maxerrabs; } gamma_display; +#define ALPHA_MODE_OFFSET 4 + static void gamma_display_init(gamma_display *dp, png_modifier *pm, png_uint_32 id, double file_gamma, double screen_gamma, png_byte sbit, int threshold_test, - int speed, int use_input_precision, int strip16) + int use_input_precision, int scale16, int expand16, + int do_background, PNG_CONST png_color_16 *pointer_to_the_background_color, + double background_gamma) { /* Standard fields */ standard_display_init(&dp->this, &pm->this, id, 0/*do_interlace*/); @@ -5200,11 +6081,17 @@ gamma_display_init(gamma_display *dp, png_modifier *pm, png_uint_32 id, dp->pm = pm; dp->file_gamma = file_gamma; dp->screen_gamma = screen_gamma; + dp->background_gamma = background_gamma; dp->sbit = sbit; dp->threshold_test = threshold_test; - dp->speed = speed; dp->use_input_precision = use_input_precision; - dp->strip16 = strip16; + dp->scale16 = scale16; + dp->expand16 = expand16; + dp->do_background = do_background; + if (do_background && pointer_to_the_background_color != 0) + dp->background_color = *pointer_to_the_background_color; + else + memset(&dp->background_color, 0, sizeof dp->background_color); /* Local variable fields */ dp->maxerrout = dp->maxerrpc = dp->maxerrabs = 0; @@ -5221,12 +6108,101 @@ gamma_info_imp(gamma_display *dp, png_structp pp, png_infop pi) * are interactions with sBIT but, internally, libpng makes sbit at most * PNG_MAX_GAMMA_8 when doing the following. */ - if (dp->strip16) -# ifdef PNG_READ_16_TO_8_SUPPORTED - png_set_strip_16(pp); + if (dp->scale16) +# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED + png_set_scale_16(pp); +# else + /* The following works both in 1.5.4 and earlier versions: */ +# ifdef PNG_READ_16_TO_8_SUPPORTED + png_set_strip_16(pp); +# else + png_error(pp, "scale16 (16 to 8 bit conversion) not supported"); +# endif +# endif + + if (dp->expand16) +# ifdef PNG_READ_EXPAND_16_SUPPORTED + png_set_expand_16(pp); +# else + png_error(pp, "expand16 (8 to 16 bit conversion) not supported"); +# endif + + if (dp->do_background >= ALPHA_MODE_OFFSET) + { +# ifdef PNG_READ_ALPHA_MODE_SUPPORTED + { + /* This tests the alpha mode handling, if supported. */ + int mode = dp->do_background - ALPHA_MODE_OFFSET; + + /* The gamma value is the output gamma, and is in the standard, + * non-inverted, represenation. It provides a default for the PNG file + * gamma, but since the file has a gAMA chunk this does not matter. + */ + PNG_CONST double sg = dp->screen_gamma; +# ifndef PNG_FLOATING_POINT_SUPPORTED + PNG_CONST png_fixed_point g = (png_fixed_point)(sg*100000+.5); +# endif + +# ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_alpha_mode(pp, mode, sg); +# else + png_set_alpha_mode_fixed(pp, mode, g); +# endif + + /* However, for the standard Porter-Duff algorithm the output defaults + * to be linear, so if the test requires non-linear output it must be + * corrected here. + */ + if (mode == PNG_ALPHA_STANDARD && sg != 1) + { +# ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_gamma(pp, sg, dp->file_gamma); +# else + png_fixed_point f = (png_fixed_point)(dp->file_gamma*100000+.5); + png_set_gamma_fixed(pp, g, f); +# endif + } + } # else - png_error(pp, "strip16 (16 to 8 bit conversion) not supported"); + png_error(pp, "alpha mode handling not supported"); # endif + } + + else + { + /* Set up gamma processing. */ +# ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_gamma(pp, dp->screen_gamma, dp->file_gamma); +# else + { + png_fixed_point s = (png_fixed_point)(dp->screen_gamma*100000+.5); + png_fixed_point f = (png_fixed_point)(dp->file_gamma*100000+.5); + png_set_gamma_fixed(pp, s, f); + } +# endif + + if (dp->do_background) + { +# ifdef PNG_READ_BACKGROUND_SUPPORTED + /* NOTE: this assumes the caller provided the correct background gamma! + */ + PNG_CONST double bg = dp->background_gamma; +# ifndef PNG_FLOATING_POINT_SUPPORTED + PNG_CONST png_fixed_point g = (png_fixed_point)(bg*100000+.5); +# endif + +# ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_background(pp, &dp->background_color, dp->do_background, + 0/*need_expand*/, bg); +# else + png_set_background_fixed(pp, &dp->background_color, + dp->do_background, 0/*need_expand*/, g); +# endif +# else + png_error(pp, "png_set_background not supported"); +# endif + } + } png_read_update_info(pp, pi); @@ -5240,16 +6216,759 @@ gamma_info(png_structp pp, png_infop pi) gamma_info_imp(png_get_progressive_ptr(pp), pp, pi); } +/* Validate a single component value - the routine gets the input and output + * sample values as unscaled PNG component values along with a cache of all the + * information required to validate the values. + */ +typedef struct validate_info +{ + png_structp pp; + gamma_display *dp; + png_byte sbit; + int use_input_precision; + int do_background; + int scale16; + unsigned int sbit_max; + unsigned int isbit_shift; + unsigned int outmax; + + double gamma_correction; /* Overall correction required. */ + double file_inverse; /* Inverse of file gamma. */ + double screen_gamma; + double screen_inverse; /* Inverse of screen gamma. */ + + double background_red; /* Linear background value, red or gray. */ + double background_green; + double background_blue; + + double maxabs; + double maxpc; + double maxcalc; + double maxout; + double maxout_total; /* Total including quantization error */ + double outlog; + int outquant; +} +validate_info; + +static void +init_validate_info(validate_info *vi, gamma_display *dp, png_struct *pp, + int in_depth, int out_depth) +{ + PNG_CONST unsigned int outmax = (1U<<out_depth)-1; + + vi->pp = pp; + vi->dp = dp; + + if (dp->sbit > 0 && dp->sbit < in_depth) + { + vi->sbit = dp->sbit; + vi->isbit_shift = in_depth - dp->sbit; + } + + else + { + vi->sbit = (png_byte)in_depth; + vi->isbit_shift = 0; + } + + vi->sbit_max = (1U << vi->sbit)-1; + + /* This mimics the libpng threshold test, '0' is used to prevent gamma + * correction in the validation test. + */ + vi->screen_gamma = dp->screen_gamma; + if (fabs(vi->screen_gamma-1) < PNG_GAMMA_THRESHOLD) + vi->screen_gamma = vi->screen_inverse = 0; + else + vi->screen_inverse = 1/vi->screen_gamma; + + vi->use_input_precision = dp->use_input_precision; + vi->outmax = outmax; + vi->maxabs = abserr(dp->pm, in_depth, out_depth); + vi->maxpc = pcerr(dp->pm, in_depth, out_depth); + vi->maxcalc = calcerr(dp->pm, in_depth, out_depth); + vi->maxout = outerr(dp->pm, in_depth, out_depth); + vi->outquant = output_quantization_factor(dp->pm, in_depth, out_depth); + vi->maxout_total = vi->maxout + vi->outquant * .5; + vi->outlog = outlog(dp->pm, in_depth, out_depth); + + if ((dp->this.colour_type & PNG_COLOR_MASK_ALPHA) != 0 || + (dp->this.colour_type == 3 && dp->this.is_transparent)) + { + vi->do_background = dp->do_background; + + if (vi->do_background != 0) + { + PNG_CONST double bg_inverse = 1/dp->background_gamma; + double r, g, b; + + /* Caller must at least put the gray value into the red channel */ + r = dp->background_color.red; r /= outmax; + g = dp->background_color.green; g /= outmax; + b = dp->background_color.blue; b /= outmax; + +# if 0 + /* libpng doesn't do this optimization, if we do pngvalid will fail. + */ + if (fabs(bg_inverse-1) >= PNG_GAMMA_THRESHOLD) +# endif + { + r = pow(r, bg_inverse); + g = pow(g, bg_inverse); + b = pow(b, bg_inverse); + } + + vi->background_red = r; + vi->background_green = g; + vi->background_blue = b; + } + } + else + vi->do_background = 0; + + if (vi->do_background == 0) + vi->background_red = vi->background_green = vi->background_blue = 0; + + vi->gamma_correction = 1/(dp->file_gamma*dp->screen_gamma); + if (fabs(vi->gamma_correction-1) < PNG_GAMMA_THRESHOLD) + vi->gamma_correction = 0; + + vi->file_inverse = 1/dp->file_gamma; + if (fabs(vi->file_inverse-1) < PNG_GAMMA_THRESHOLD) + vi->file_inverse = 0; + + vi->scale16 = dp->scale16; +} + +/* This function handles composition of a single non-alpha component. The + * argument is the input sample value, in the range 0..1, and the alpha value. + * The result is the composed, linear, input sample. If alpha is less than zero + * this is the alpha component and the function should not be called! + */ +static double +gamma_component_compose(int do_background, double input_sample, double alpha, + double background, int *compose) +{ + switch (do_background) + { + case PNG_BACKGROUND_GAMMA_SCREEN: + case PNG_BACKGROUND_GAMMA_FILE: + case PNG_BACKGROUND_GAMMA_UNIQUE: + /* Standard PNG background processing. */ + if (alpha < 1) + { + if (alpha > 0) + { + input_sample = input_sample * alpha + background * (1-alpha); + if (compose != NULL) + *compose = 1; + } + + else + input_sample = background; + } + break; + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED + case ALPHA_MODE_OFFSET + PNG_ALPHA_STANDARD: + case ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN: + /* The components are premultiplied in either case and the output is + * gamma encoded (to get standard Porter-Duff we expect the output + * gamma to be set to 1.0!) + */ + case ALPHA_MODE_OFFSET + PNG_ALPHA_OPTIMIZED: + /* The optimization is that the partial-alpha entries are linear + * while the opaque pixels are gamma encoded, but this only affects the + * output encoding. + */ + if (alpha < 1) + { + if (alpha > 0) + { + input_sample *= alpha; + if (compose != NULL) + *compose = 1; + } + + else + input_sample = 0; + } + break; +#endif + + default: + /* Standard cases where no compositing is done (so the component + * value is already correct.) + */ + break; + } + + return input_sample; +} + +/* This API returns the encoded *input* component, in the range 0..1 */ +static double +gamma_component_validate(PNG_CONST char *name, PNG_CONST validate_info *vi, + PNG_CONST unsigned int id, PNG_CONST unsigned int od, + PNG_CONST double alpha /* <0 for the alpha channel itself */, + PNG_CONST double background /* component background value */) +{ + PNG_CONST unsigned int isbit = id >> vi->isbit_shift; + PNG_CONST unsigned int sbit_max = vi->sbit_max; + PNG_CONST unsigned int outmax = vi->outmax; + PNG_CONST int do_background = vi->do_background; + + double i; + + /* First check on the 'perfect' result obtained from the digitized input + * value, id, and compare this against the actual digitized result, 'od'. + * 'i' is the input result in the range 0..1: + */ + i = isbit; i /= sbit_max; + + /* Check for the fast route: if we don't do any background composition or if + * this is the alpha channel ('alpha' < 0) or if the pixel is opaque then + * just use the gamma_correction field to correct to the final output gamma. + */ + if (alpha == 1 /* opaque pixel component */ || !do_background +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED + || do_background == ALPHA_MODE_OFFSET + PNG_ALPHA_PNG +#endif + || (alpha < 0 /* alpha channel */ +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED + && do_background != ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN +#endif + )) + { + /* Then get the gamma corrected version of 'i' and compare to 'od', any + * error less than .5 is insignificant - just quantization of the output + * value to the nearest digital value (nevertheless the error is still + * recorded - it's interesting ;-) + */ + double encoded_sample = i; + double encoded_error; + + /* alpha less than 0 indicates the alpha channel, which is always linear + */ + if (alpha >= 0 && vi->gamma_correction > 0) + encoded_sample = pow(encoded_sample, vi->gamma_correction); + encoded_sample *= outmax; + + encoded_error = fabs(od-encoded_sample); + + if (encoded_error > vi->dp->maxerrout) + vi->dp->maxerrout = encoded_error; + + if (encoded_error < vi->maxout_total && encoded_error < vi->outlog) + return i; + } + + /* The slow route - attempt to do linear calculations. */ + /* There may be an error, or background processing is required, so calculate + * the actual sample values - unencoded light intensity values. Note that in + * practice these are not completely unencoded because they include a + * 'viewing correction' to decrease or (normally) increase the perceptual + * contrast of the image. There's nothing we can do about this - we don't + * know what it is - so assume the unencoded value is perceptually linear. + */ + { + double input_sample = i; /* In range 0..1 */ + double output, error, encoded_sample, encoded_error; + double es_lo, es_hi; + int compose = 0; /* Set to one if composition done */ + int output_is_encoded; /* Set if encoded to screen gamma */ + int log_max_error = 1; /* Check maximum error values */ + png_const_charp pass = 0; /* Reason test passes (or 0 for fail) */ + + /* Convert to linear light (with the above caveat.) The alpha channel is + * already linear. + */ + if (alpha >= 0) + { + int tcompose; + + if (vi->file_inverse > 0) + input_sample = pow(input_sample, vi->file_inverse); + + /* Handle the compose processing: */ + tcompose = 0; + input_sample = gamma_component_compose(do_background, input_sample, + alpha, background, &tcompose); + + if (tcompose) + compose = 1; + } + + /* And similarly for the output value, but we need to check the background + * handling to linearize it correctly. + */ + output = od; + output /= outmax; + + output_is_encoded = vi->screen_gamma > 0; + + if (alpha < 0) /* The alpha channel */ + { +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED + if (do_background != ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN) +#endif + { + /* In all other cases the output alpha channel is linear already, + * don't log errors here, they are much larger in linear data. + */ + output_is_encoded = 0; + log_max_error = 0; + } + } + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED + else /* A component */ + { + if (do_background == ALPHA_MODE_OFFSET + PNG_ALPHA_OPTIMIZED && + alpha < 1) /* the optimized case - linear output */ + { + if (alpha > 0) log_max_error = 0; + output_is_encoded = 0; + } + } +#endif + + if (output_is_encoded) + output = pow(output, vi->screen_gamma); + + /* Calculate (or recalculate) the encoded_sample value and repeat the + * check above (unnecessary if we took the fast route, but harmless.) + */ + encoded_sample = input_sample; + if (output_is_encoded) + encoded_sample = pow(encoded_sample, vi->screen_inverse); + encoded_sample *= outmax; + + encoded_error = fabs(od-encoded_sample); + + /* Don't log errors in the alpha channel, or the 'optimized' case, + * neither are significant to the overall perception. + */ + if (log_max_error && encoded_error > vi->dp->maxerrout) + vi->dp->maxerrout = encoded_error; + + if (encoded_error < vi->maxout_total) + { + if (encoded_error < vi->outlog) + return i; + + /* Test passed but error is bigger than the log limit, record why the + * test passed: + */ + pass = "less than maxout:\n"; + } + + /* i: the original input value in the range 0..1 + * + * pngvalid calculations: + * input_sample: linear result; i linearized and composed, range 0..1 + * encoded_sample: encoded result; input_sample scaled to ouput bit depth + * + * libpng calculations: + * output: linear result; od scaled to 0..1 and linearized + * od: encoded result from libpng + */ + + /* Now we have the numbers for real errors, both absolute values as as a + * percentage of the correct value (output): + */ + error = fabs(input_sample-output); + + if (log_max_error && error > vi->dp->maxerrabs) + vi->dp->maxerrabs = error; + + /* The following is an attempt to ignore the tendency of quantization to + * dominate the percentage errors for lower result values: + */ + if (log_max_error && input_sample > .5) + { + double percentage_error = error/input_sample; + if (percentage_error > vi->dp->maxerrpc) + vi->dp->maxerrpc = percentage_error; + } + + /* Now calculate the digitization limits for 'encoded_sample' using the + * 'max' values. Note that maxout is in the encoded space but maxpc and + * maxabs are in linear light space. + * + * First find the maximum error in linear light space, range 0..1: + */ + { + double tmp = input_sample * vi->maxpc; + if (tmp < vi->maxabs) tmp = vi->maxabs; + /* If 'compose' is true the composition was done in linear space using + * integer arithmetic. This introduces an extra error of +/- 0.5 (at + * least) in the integer space used. 'maxcalc' records this, taking + * into account the possibility that even for 16 bit output 8 bit space + * may have been used. + */ + if (compose && tmp < vi->maxcalc) tmp = vi->maxcalc; + + /* The 'maxout' value refers to the encoded result, to compare with + * this encode input_sample adjusted by the maximum error (tmp) above. + */ + es_lo = encoded_sample - vi->maxout; + + if (es_lo > 0 && input_sample-tmp > 0) + { + double low_value = input_sample-tmp; + if (output_is_encoded) + low_value = pow(low_value, vi->screen_inverse); + low_value *= outmax; + if (low_value < es_lo) es_lo = low_value; + + /* Quantize this appropriately: */ + es_lo = ceil(es_lo / vi->outquant - .5) * vi->outquant; + } + + else + es_lo = 0; + + es_hi = encoded_sample + vi->maxout; + + if (es_hi < outmax && input_sample+tmp < 1) + { + double high_value = input_sample+tmp; + if (output_is_encoded) + high_value = pow(high_value, vi->screen_inverse); + high_value *= outmax; + if (high_value > es_hi) es_hi = high_value; + + es_hi = floor(es_hi / vi->outquant + .5) * vi->outquant; + } + + else + es_hi = outmax; + } + + /* The primary test is that the final encoded value returned by the + * library should be between the two limits (inclusive) that were + * calculated above. + */ + if (od >= es_lo && od <= es_hi) + { + /* The value passes, but we may need to log the information anyway. */ + if (encoded_error < vi->outlog) + return i; + + if (pass == 0) + pass = "within digitization limits:\n"; + } + + { + /* There has been an error in processing, or we need to log this + * value. + */ + double is_lo, is_hi; + + /* pass is set at this point if either of the tests above would have + * passed. Don't do these additional tests here - just log the + * original [es_lo..es_hi] values. + */ + if (pass == 0 && vi->use_input_precision) + { + /* Ok, something is wrong - this actually happens in current libpng + * 16-to-8 processing. Assume that the input value (id, adjusted + * for sbit) can be anywhere between value-.5 and value+.5 - quite a + * large range if sbit is low. + */ + double tmp = (isbit - .5)/sbit_max; + + if (tmp <= 0) + tmp = 0; + + else if (alpha >= 0 && vi->file_inverse > 0 && tmp < 1) + tmp = pow(tmp, vi->file_inverse); + + tmp = gamma_component_compose(do_background, tmp, alpha, background, + NULL); + + if (output_is_encoded && tmp > 0 && tmp < 1) + tmp = pow(tmp, vi->screen_inverse); + + is_lo = ceil(outmax * tmp - vi->maxout_total); + + if (is_lo < 0) + is_lo = 0; + + tmp = (isbit + .5)/sbit_max; + + if (tmp <= 0) + tmp = 0; + + else if (alpha >= 0 && vi->file_inverse > 0 && tmp < 1) + tmp = pow(tmp, vi->file_inverse); + + tmp = gamma_component_compose(do_background, tmp, alpha, background, + NULL); + + if (output_is_encoded && tmp > 0 && tmp < 1) + tmp = pow(tmp, vi->screen_inverse); + + is_hi = floor(outmax * tmp + vi->maxout_total); + + if (is_hi > outmax) + is_hi = outmax; + + if (!(od < is_lo || od > is_hi)) + { + if (encoded_error < vi->outlog) + return i; + + pass = "within input precision limits:\n"; + } + + /* One last chance. If this is an alpha channel and the 16to8 + * option has been used and 'inaccurate' scaling is used then the + * bit reduction is obtained by simply using the top 8 bits of the + * value. + * + * This is only done for older libpng versions when the 'inaccurate' + * (chop) method of scaling was used. + */ +# ifndef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED +# if PNG_LIBPNG_VER < 10504 + /* This may be required for other components in the future, + * but at present the presence of gamma correction effectively + * prevents the errors in the component scaling (I don't quite + * understand why, but since it's better this way I care not + * to ask, JB 20110419.) + */ + if (pass == 0 && alpha < 0 && vi->scale16 && vi->sbit > 8 && + vi->sbit + vi->isbit_shift == 16) + { + tmp = ((id >> 8) - .5)/255; + + if (tmp > 0) + { + is_lo = ceil(outmax * tmp - vi->maxout_total); + if (is_lo < 0) is_lo = 0; + } + + else + is_lo = 0; + + tmp = ((id >> 8) + .5)/255; + + if (tmp < 1) + { + is_hi = floor(outmax * tmp + vi->maxout_total); + if (is_hi > outmax) is_hi = outmax; + } + + else + is_hi = outmax; + + if (!(od < is_lo || od > is_hi)) + { + if (encoded_error < vi->outlog) + return i; + + pass = "within 8 bit limits:\n"; + } + } +# endif +# endif + } + else /* !use_input_precision */ + is_lo = es_lo, is_hi = es_hi; + + /* Attempt to output a meaningful error/warning message: the message + * output depends on the background/composite operation being performed + * because this changes what parameters were actually used above. + */ + { + size_t pos = 0; + /* Need either 1/255 or 1/65535 precision here; 3 or 6 decimal + * places. Just use outmax to work out which. + */ + int precision = (outmax >= 1000 ? 6 : 3); + int use_input=1, use_background=0, do_compose=0; + char msg[256]; + + if (pass != 0) + pos = safecat(msg, sizeof msg, pos, "\n\t"); + + /* Set up the various flags, the output_is_encoded flag above + * is also used below. do_compose is just a double check. + */ + switch (do_background) + { + case PNG_BACKGROUND_GAMMA_SCREEN: + case PNG_BACKGROUND_GAMMA_FILE: + case PNG_BACKGROUND_GAMMA_UNIQUE: + use_background = (alpha >= 0 && alpha < 1); + /*FALL THROUGH*/ +# ifdef PNG_READ_ALPHA_MODE_SUPPORTED + case ALPHA_MODE_OFFSET + PNG_ALPHA_STANDARD: + case ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN: + case ALPHA_MODE_OFFSET + PNG_ALPHA_OPTIMIZED: +# endif /* ALPHA_MODE_SUPPORTED */ + do_compose = (alpha >= 0 && alpha < 1); + use_input = (alpha != 0); + break; + + default: + break; + } + + /* Check the 'compose' flag */ + if (compose != do_compose) + png_error(vi->pp, "internal error (compose)"); + + /* 'name' is the component name */ + pos = safecat(msg, sizeof msg, pos, name); + pos = safecat(msg, sizeof msg, pos, "("); + pos = safecatn(msg, sizeof msg, pos, id); + if (use_input || pass != 0/*logging*/) + { + if (isbit != id) + { + /* sBIT has reduced the precision of the input: */ + pos = safecat(msg, sizeof msg, pos, ", sbit("); + pos = safecatn(msg, sizeof msg, pos, vi->sbit); + pos = safecat(msg, sizeof msg, pos, "): "); + pos = safecatn(msg, sizeof msg, pos, isbit); + } + pos = safecat(msg, sizeof msg, pos, "/"); + /* The output is either "id/max" or "id sbit(sbit): isbit/max" */ + pos = safecatn(msg, sizeof msg, pos, vi->sbit_max); + } + pos = safecat(msg, sizeof msg, pos, ")"); + + /* A component may have been multiplied (in linear space) by the + * alpha value, 'compose' says whether this is relevant. + */ + if (compose || pass != 0) + { + /* If any form of composition is being done report our + * calculated linear value here (the code above doesn't record + * the input value before composition is performed, so what + * gets reported is the value after composition.) + */ + if (use_input || pass != 0) + { + if (vi->file_inverse > 0) + { + pos = safecat(msg, sizeof msg, pos, "^"); + pos = safecatd(msg, sizeof msg, pos, vi->file_inverse, 2); + } + + else + pos = safecat(msg, sizeof msg, pos, "[linear]"); + + pos = safecat(msg, sizeof msg, pos, "*(alpha)"); + pos = safecatd(msg, sizeof msg, pos, alpha, precision); + } + + /* Now record the *linear* background value if it was used + * (this function is not passed the original, non-linear, + * value but it is contained in the test name.) + */ + if (use_background) + { + pos = safecat(msg, sizeof msg, pos, use_input ? "+" : " "); + pos = safecat(msg, sizeof msg, pos, "(background)"); + pos = safecatd(msg, sizeof msg, pos, background, precision); + pos = safecat(msg, sizeof msg, pos, "*"); + pos = safecatd(msg, sizeof msg, pos, 1-alpha, precision); + } + } + + /* Report the calculated value (input_sample) and the linearized + * libpng value (output) unless this is just a component gamma + * correction. + */ + if (compose || alpha < 0 || pass != 0) + { + pos = safecat(msg, sizeof msg, pos, + pass != 0 ? " =\n\t" : " = "); + pos = safecatd(msg, sizeof msg, pos, input_sample, precision); + pos = safecat(msg, sizeof msg, pos, " (libpng: "); + pos = safecatd(msg, sizeof msg, pos, output, precision); + pos = safecat(msg, sizeof msg, pos, ")"); + + /* Finally report the output gamma encoding, if any. */ + if (output_is_encoded) + { + pos = safecat(msg, sizeof msg, pos, " ^"); + pos = safecatd(msg, sizeof msg, pos, vi->screen_inverse, 2); + pos = safecat(msg, sizeof msg, pos, "(to screen) ="); + } + + else + pos = safecat(msg, sizeof msg, pos, " [screen is linear] ="); + } + + if ((!compose && alpha >= 0) || pass != 0) + { + if (pass != 0) /* logging */ + pos = safecat(msg, sizeof msg, pos, "\n\t[overall:"); + + /* This is the non-composition case, the internal linear + * values are irrelevant (though the log below will reveal + * them.) Output a much shorter warning/error message and report + * the overall gamma correction. + */ + if (vi->gamma_correction > 0) + { + pos = safecat(msg, sizeof msg, pos, " ^"); + pos = safecatd(msg, sizeof msg, pos, vi->gamma_correction, 2); + pos = safecat(msg, sizeof msg, pos, "(gamma correction) ="); + } + + else + pos = safecat(msg, sizeof msg, pos, + " [no gamma correction] ="); + + if (pass != 0) + pos = safecat(msg, sizeof msg, pos, "]"); + } + + /* This is our calculated encoded_sample which should (but does + * not) match od: + */ + pos = safecat(msg, sizeof msg, pos, pass != 0 ? "\n\t" : " "); + pos = safecatd(msg, sizeof msg, pos, is_lo, 1); + pos = safecat(msg, sizeof msg, pos, " < "); + pos = safecatd(msg, sizeof msg, pos, encoded_sample, 1); + pos = safecat(msg, sizeof msg, pos, " (libpng: "); + pos = safecatn(msg, sizeof msg, pos, od); + pos = safecat(msg, sizeof msg, pos, ")"); + pos = safecat(msg, sizeof msg, pos, "/"); + pos = safecatn(msg, sizeof msg, pos, outmax); + pos = safecat(msg, sizeof msg, pos, " < "); + pos = safecatd(msg, sizeof msg, pos, is_hi, 1); + + if (pass == 0) /* The error condition */ + { +# ifdef PNG_WARNINGS_SUPPORTED + png_warning(vi->pp, msg); +# else + store_warning(vi->pp, msg); +# endif + } + + else /* logging this value */ + store_verbose(&vi->dp->pm->this, vi->pp, pass, msg); + } + } + } + + return i; +} + static void -gamma_image_validate(gamma_display *dp, png_structp pp, png_infop pi, - png_const_bytep pRow) +gamma_image_validate(gamma_display *dp, png_structp pp, png_infop pi) { /* Get some constants derived from the input and output file formats: */ - PNG_CONST png_byte sbit = dp->sbit; - PNG_CONST double file_gamma = dp->file_gamma; - PNG_CONST double screen_gamma = dp->screen_gamma; - PNG_CONST int use_input_precision = dp->use_input_precision; - PNG_CONST int speed = dp->speed; + PNG_CONST png_store* PNG_CONST ps = dp->this.ps; PNG_CONST png_byte in_ct = dp->this.colour_type; PNG_CONST png_byte in_bd = dp->this.bit_depth; PNG_CONST png_uint_32 w = dp->this.w; @@ -5257,10 +6976,6 @@ gamma_image_validate(gamma_display *dp, png_structp pp, png_infop pi, PNG_CONST size_t cbRow = dp->this.cbRow; PNG_CONST png_byte out_ct = png_get_color_type(pp, pi); PNG_CONST png_byte out_bd = png_get_bit_depth(pp, pi); - PNG_CONST unsigned int outmax = (1U<<out_bd)-1; - PNG_CONST double maxabs = abserr(dp->pm, out_bd); - PNG_CONST double maxout = outerr(dp->pm, out_bd); - PNG_CONST double maxpc = pcerr(dp->pm, out_bd); /* There are three sources of error, firstly the quantization in the * file encoding, determined by sbit and/or the file depth, secondly @@ -5298,201 +7013,133 @@ gamma_image_validate(gamma_display *dp, png_structp pp, png_infop pi, * * Because there is limited precision in the input it is arguable that * an acceptable result is any valid result from input-.5 to input+.5. - * The basic tests below do not do this, however if - * 'use_input_precision' is set a subsequent test is performed below. + * The basic tests below do not do this, however if 'use_input_precision' + * is set a subsequent test is performed below. */ - PNG_CONST int processing = (fabs(screen_gamma*file_gamma-1) >= - PNG_GAMMA_THRESHOLD && !dp->threshold_test && !speed && in_ct != 3) || - in_bd != out_bd; - PNG_CONST unsigned int samples_per_pixel = (out_ct & 2U) ? 3U : 1U; + int processing; + png_uint_32 y; + PNG_CONST store_palette_entry *in_palette = dp->this.palette; + PNG_CONST int in_is_transparent = dp->this.is_transparent; + int out_npalette = -1; + int out_is_transparent = 0; /* Just refers to the palette case */ + store_palette out_palette; + validate_info vi; + + /* Check for row overwrite errors */ + store_image_check(dp->this.ps, pp, 0); + + /* Supply the input and output sample depths here - 8 for an indexed image, + * otherwise the bit depth. + */ + init_validate_info(&vi, dp, pp, in_ct==3?8:in_bd, out_ct==3?8:out_bd); - PNG_CONST double gamma_correction = 1/(file_gamma*screen_gamma);/* Overall */ + processing = (vi.gamma_correction > 0 && !dp->threshold_test) + || in_bd != out_bd || in_ct != out_ct || vi.do_background; - double maxerrout = 0, maxerrabs = 0, maxerrpc = 0; - png_uint_32 y; + /* TODO: FIX THIS: MAJOR BUG! If the transformations all happen inside + * the palette there is no way of finding out, because libpng fails to + * update the palette on png_read_update_info. Indeed, libpng doesn't + * even do the required work until much later, when it doesn't have any + * info pointer. Oops. For the moment 'processing' is turned off if + * out_ct is palette. + */ + if (in_ct == 3 && out_ct == 3) + processing = 0; - for (y=0; y<h; ++y, pRow += cbRow) + if (processing && out_ct == 3) + out_is_transparent = read_palette(out_palette, &out_npalette, pp, pi); + + for (y=0; y<h; ++y) { - unsigned int s, x; + png_const_bytep pRow = store_image_row(ps, pp, 0, y); png_byte std[STANDARD_ROWMAX]; transform_row(pp, std, in_ct, in_bd, y); if (processing) { - for (x=0; x<w; ++x) for (s=0; s<samples_per_pixel; ++s) - { - /* Input sample values: */ - PNG_CONST unsigned int - id = sample(std, in_ct, in_bd, x, s); + unsigned int x; - PNG_CONST unsigned int - od = sample(pRow, out_ct, out_bd, x, s); - - PNG_CONST unsigned int - isbit = id >> (in_bd-sbit); - - double i, input_sample, encoded_sample, output; - double encoded_error, error; - double es_lo, es_hi; - - /* First check on the 'perfect' result obtained from the - * digitized input value, id, and compare this against the - * actual digitized result, 'od'. 'i' is the input result - * in the range 0..1: - * - * NOTE: sBIT should be taken into account here but isn't, - * as described above. - */ - i = isbit; i /= (1U<<sbit)-1; - - /* Then get the gamma corrected version of 'i' and compare - * to 'od', any error less than .5 is insignificant - just - * quantization of the output value to the nearest digital - * value (nevertheless the error is still recorded - it's - * interesting ;-) - */ - encoded_sample = pow(i, gamma_correction) * outmax; - encoded_error = fabs(od-encoded_sample); - - if (encoded_error > maxerrout) - maxerrout = encoded_error; - - if (encoded_error < .5+maxout) - continue; - - /* There may be an error, so calculate the actual sample - * values - unencoded light intensity values. Note that - * in practice these are not unencoded because they - * include a 'viewing correction' to decrease or - * (normally) increase the perceptual contrast of the - * image. There's nothing we can do about this - we don't - * know what it is - so assume the unencoded value is - * perceptually linear. - */ - input_sample = pow(i, 1/file_gamma); /* In range 0..1 */ - output = od; - output /= outmax; - output = pow(output, screen_gamma); - - /* Now we have the numbers for real errors, both absolute - * values as as a percentage of the correct value (output): - */ - error = fabs(input_sample-output); - - if (error > maxerrabs) - maxerrabs = error; + for (x=0; x<w; ++x) + { + double alpha = 1; /* serves as a flag value */ - /* The following is an attempt to ignore the tendency of - * quantization to dominate the percentage errors for low - * output sample values: - */ - if (input_sample*maxpc > .5+maxabs) - { - double percentage_error = error/input_sample; - if (percentage_error > maxerrpc) maxerrpc = percentage_error; - } + /* Record the palette index for index images. */ + PNG_CONST unsigned int in_index = + in_ct == 3 ? sample(std, 3, in_bd, x, 0) : 256; + PNG_CONST unsigned int out_index = + out_ct == 3 ? sample(std, 3, out_bd, x, 0) : 256; - /* Now calculate the digitization limits for - * 'encoded_sample' using the 'max' values. Note that - * maxout is in the encoded space but maxpc and maxabs are - * in linear light space. - * - * First find the maximum error in linear light space, - * range 0..1: + /* Handle input alpha - png_set_background will cause the output + * alpha to disappear so there is nothing to check. */ + if ((in_ct & PNG_COLOR_MASK_ALPHA) != 0 || (in_ct == 3 && + in_is_transparent)) { - double tmp = input_sample * maxpc; - if (tmp < maxabs) tmp = maxabs; + PNG_CONST unsigned int input_alpha = in_ct == 3 ? + dp->this.palette[in_index].alpha : + sample(std, in_ct, in_bd, x, samples_per_pixel); - /* Low bound - the minimum of the three: */ - es_lo = encoded_sample - maxout; + unsigned int output_alpha = 65536 /* as a flag value */; - if (es_lo > 0 && input_sample-tmp > 0) + if (out_ct == 3) { - double low_value = outmax * pow(input_sample-tmp, - 1/screen_gamma); - if (low_value < es_lo) es_lo = low_value; + if (out_is_transparent) + output_alpha = out_palette[out_index].alpha; } - else - es_lo = 0; + else if ((out_ct & PNG_COLOR_MASK_ALPHA) != 0) + output_alpha = sample(pRow, out_ct, out_bd, x, + samples_per_pixel); - es_hi = encoded_sample + maxout; + if (output_alpha != 65536) + alpha = gamma_component_validate("alpha", &vi, input_alpha, + output_alpha, -1/*alpha*/, 0/*background*/); - if (es_hi < outmax && input_sample+tmp < 1) + else /* no alpha in output */ { - double high_value = outmax * pow(input_sample+tmp, - 1/screen_gamma); - if (high_value > es_hi) es_hi = high_value; + /* This is a copy of the calculation of 'i' above in order to + * have the alpha value to use in the background calculation. + */ + alpha = input_alpha >> vi.isbit_shift; + alpha /= vi.sbit_max; } - - else - es_hi = outmax; } - /* The primary test is that the final encoded value - * returned by the library should be between the two limits - * (inclusive) that were calculated above. At this point - * quantization of the output must be taken into account. - */ - if (od+.5 < es_lo || od-.5 > es_hi) + /* Handle greyscale or RGB components. */ + if ((in_ct & PNG_COLOR_MASK_COLOR) == 0) /* greyscale */ + (void)gamma_component_validate("gray", &vi, + sample(std, in_ct, in_bd, x, 0), + sample(pRow, out_ct, out_bd, x, 0), alpha/*component*/, + vi.background_red); + else /* RGB or palette */ { - /* There has been an error in processing. */ - double is_lo, is_hi; - - if (use_input_precision) - { - /* Ok, something is wrong - this actually happens in - * current libpng sbit processing. Assume that the - * input value (id, adjusted for sbit) can be - * anywhere between value-.5 and value+.5 - quite a - * large range if sbit is low. - */ - double tmp = (isbit - .5)/((1U<<sbit)-1); - - if (tmp > 0) - { - is_lo = outmax * pow(tmp, gamma_correction) - maxout; - if (is_lo < 0) is_lo = 0; - } - - else - is_lo = 0; - - tmp = (isbit + .5)/((1U<<sbit)-1); - - if (tmp < 1) - { - is_hi = outmax * pow(tmp, gamma_correction) + maxout; - if (is_hi > outmax) is_hi = outmax; - } - - else - is_hi = outmax; - - if (!(od+.5 < is_lo || od-.5 > is_hi)) - continue; - } - else - is_lo = es_lo, is_hi = es_hi; - - { - char msg[256]; - - sprintf(msg, - "error: %.3f; %u{%u;%u} -> %u not %.2f (%.1f-%.1f)", - od-encoded_sample, id, sbit, isbit, od, - encoded_sample, is_lo, is_hi); - - png_warning(pp, msg); - } + (void)gamma_component_validate("red", &vi, + in_ct == 3 ? in_palette[in_index].red : + sample(std, in_ct, in_bd, x, 0), + out_ct == 3 ? out_palette[out_index].red : + sample(pRow, out_ct, out_bd, x, 0), + alpha/*component*/, vi.background_red); + + (void)gamma_component_validate("green", &vi, + in_ct == 3 ? in_palette[in_index].green : + sample(std, in_ct, in_bd, x, 1), + out_ct == 3 ? out_palette[out_index].green : + sample(pRow, out_ct, out_bd, x, 1), + alpha/*component*/, vi.background_green); + + (void)gamma_component_validate("blue", &vi, + in_ct == 3 ? in_palette[in_index].blue : + sample(std, in_ct, in_bd, x, 2), + out_ct == 3 ? out_palette[out_index].blue : + sample(pRow, out_ct, out_bd, x, 2), + alpha/*component*/, vi.background_blue); } } } - else if (!speed && memcmp(std, pRow, cbRow) != 0) + else if (memcmp(std, pRow, cbRow) != 0) { char msg[64]; @@ -5503,9 +7150,6 @@ gamma_image_validate(gamma_display *dp, png_structp pp, png_infop pi, } } /* row (y) loop */ - dp->maxerrout = maxerrout; - dp->maxerrabs = maxerrabs; - dp->maxerrpc = maxerrpc; dp->this.ps->validated = 1; } @@ -5514,7 +7158,8 @@ gamma_end(png_structp pp, png_infop pi) { gamma_display *dp = png_get_progressive_ptr(pp); - gamma_image_validate(dp, pp, pi, dp->this.ps->image); + if (!dp->this.speed) + gamma_image_validate(dp, pp, pi); } /* A single test run checking a gamma transformation. @@ -5525,18 +7170,23 @@ gamma_end(png_structp pp, png_infop pi) */ static void gamma_test(png_modifier *pmIn, PNG_CONST png_byte colour_typeIn, - PNG_CONST png_byte bit_depthIn, PNG_CONST int interlace_typeIn, + PNG_CONST png_byte bit_depthIn, PNG_CONST int palette_numberIn, + PNG_CONST int interlace_typeIn, PNG_CONST double file_gammaIn, PNG_CONST double screen_gammaIn, PNG_CONST png_byte sbitIn, PNG_CONST int threshold_testIn, - PNG_CONST char *name, PNG_CONST int speedIn, - PNG_CONST int use_input_precisionIn, PNG_CONST int strip16In) + PNG_CONST char *name, + PNG_CONST int use_input_precisionIn, PNG_CONST int scale16In, + PNG_CONST int expand16In, PNG_CONST int do_backgroundIn, + PNG_CONST png_color_16 *bkgd_colorIn, double bkgd_gammaIn) { gamma_display d; context(&pmIn->this, fault); gamma_display_init(&d, pmIn, FILEID(colour_typeIn, bit_depthIn, - interlace_typeIn, 0, 0, 0), file_gammaIn, screen_gammaIn, sbitIn, - threshold_testIn, speedIn, use_input_precisionIn, strip16In); + palette_numberIn, interlace_typeIn, 0, 0, 0), + file_gammaIn, screen_gammaIn, sbitIn, + threshold_testIn, use_input_precisionIn, scale16In, + expand16In, do_backgroundIn, bkgd_colorIn, bkgd_gammaIn); Try { @@ -5552,23 +7202,14 @@ gamma_test(png_modifier *pmIn, PNG_CONST png_byte colour_typeIn, d.pm->modifications = NULL; gamma_modification_init(&gamma_mod, d.pm, d.file_gamma); srgb_modification_init(&srgb_mod, d.pm, 127 /*delete*/); - sbit_modification_init(&sbit_mod, d.pm, d.sbit); + if (d.sbit > 0) + sbit_modification_init(&sbit_mod, d.pm, d.sbit); modification_reset(d.pm->modifications); /* Get a png_struct for writing the image. */ pp = set_modifier_for_read(d.pm, &pi, d.this.id, name); - - /* Set up gamma processing. */ -#ifdef PNG_FLOATING_POINT_SUPPORTED - png_set_gamma(pp, d.screen_gamma, d.file_gamma); -#else - { - png_fixed_point s = floor(d.screen_gamma*100000+.5); - png_fixed_point f = floor(d.file_gamma*100000+.5); - png_set_gamma_fixed(pp, s, f); - } -#endif + standard_palette_init(&d.this); /* Introduce the correct read function. */ if (d.pm->this.progressive) @@ -5591,16 +7232,17 @@ gamma_test(png_modifier *pmIn, PNG_CONST png_byte colour_typeIn, /* Process the 'info' requirements. Only one image is generated */ gamma_info_imp(&d, pp, pi); - sequential_row(&d.this, pp, pi, NULL, d.this.ps->image); + sequential_row(&d.this, pp, pi, -1, 0); - gamma_image_validate(&d, pp, pi, d.this.ps->image); + if (!d.this.speed) + gamma_image_validate(&d, pp, pi); } modifier_reset(d.pm); - if (d.pm->log && !d.threshold_test && !d.speed) + if (d.pm->log && !d.threshold_test && !d.this.speed) fprintf(stderr, "%d bit %s %s: max error %f (%.2g, %2g%%)\n", - d.this.bit_depth, colour_types[d.this.colour_type], d.name, + d.this.bit_depth, colour_types[d.this.colour_type], name, d.maxerrout, d.maxerrabs, 100*d.maxerrpc); /* Log the summary values too. */ @@ -5662,6 +7304,12 @@ gamma_test(png_modifier *pmIn, PNG_CONST png_byte colour_typeIn, png_error(pp, "bad bit depth (internal: 2)"); } } + + else if (d.this.colour_type == 3) + { + if (d.maxerrout > d.pm->error_indexed) + d.pm->error_indexed = d.maxerrout; + } } Catch(fault) @@ -5679,9 +7327,11 @@ static void gamma_threshold_test(png_modifier *pm, png_byte colour_type, pos = safecat(name, sizeof name, pos, "/"); pos = safecatd(name, sizeof name, pos, screen_gamma, 3); - (void)gamma_test(pm, colour_type, bit_depth, interlace_type, file_gamma, - screen_gamma, bit_depth, 1, name, 0 /*speed*/, 0 /*no input precision*/, - 0 /*no strip16*/); + (void)gamma_test(pm, colour_type, bit_depth, 0/*palette*/, interlace_type, + file_gamma, screen_gamma, 0/*sBIT*/, 1/*threshold test*/, name, + 0 /*no input precision*/, + 0 /*no scale16*/, 0 /*no expand16*/, 0 /*no background*/, 0 /*hence*/, + 0 /*no background gamma*/); } static void @@ -5689,8 +7339,14 @@ perform_gamma_threshold_tests(png_modifier *pm) { png_byte colour_type = 0; png_byte bit_depth = 0; + int palette_number = 0; - while (next_format(&colour_type, &bit_depth)) + /* Don't test more than one instance of each palette - it's pointless, in + * fact this test is somewhat excessive since libpng doesn't make this + * decision based on colour type or bit depth! + */ + while (next_format(&colour_type, &bit_depth, &palette_number)) + if (palette_number == 0) { double test_gamma = 1.0; while (test_gamma >= .4) @@ -5714,14 +7370,15 @@ perform_gamma_threshold_tests(png_modifier *pm) static void gamma_transform_test(png_modifier *pm, PNG_CONST png_byte colour_type, PNG_CONST png_byte bit_depth, + PNG_CONST int palette_number, PNG_CONST int interlace_type, PNG_CONST double file_gamma, - PNG_CONST double screen_gamma, PNG_CONST png_byte sbit, PNG_CONST int speed, - PNG_CONST int use_input_precision, PNG_CONST int strip16) + PNG_CONST double screen_gamma, PNG_CONST png_byte sbit, + PNG_CONST int use_input_precision, PNG_CONST int scale16) { size_t pos = 0; char name[64]; - if (sbit != bit_depth) + if (sbit != bit_depth && sbit != 0) { pos = safecat(name, sizeof name, pos, "sbit("); pos = safecatn(name, sizeof name, pos, sbit); @@ -5731,34 +7388,33 @@ static void gamma_transform_test(png_modifier *pm, else pos = safecat(name, sizeof name, pos, "gamma "); - if (strip16) + if (scale16) pos = safecat(name, sizeof name, pos, "16to8 "); pos = safecatd(name, sizeof name, pos, file_gamma, 3); pos = safecat(name, sizeof name, pos, "->"); pos = safecatd(name, sizeof name, pos, screen_gamma, 3); - gamma_test(pm, colour_type, bit_depth, interlace_type, file_gamma, - screen_gamma, sbit, 0, name, speed, use_input_precision, strip16); + gamma_test(pm, colour_type, bit_depth, palette_number, interlace_type, + file_gamma, screen_gamma, sbit, 0, name, use_input_precision, + scale16, pm->test_gamma_expand16, 0 , 0, 0); } -static void perform_gamma_transform_tests(png_modifier *pm, int speed) +static void perform_gamma_transform_tests(png_modifier *pm) { png_byte colour_type = 0; png_byte bit_depth = 0; + int palette_number = 0; - /* Ignore palette images - the gamma correction happens on the palette entry, - * haven't got the tests for this yet. - */ - while (next_format(&colour_type, &bit_depth)) if (colour_type != 3) + while (next_format(&colour_type, &bit_depth, &palette_number)) { unsigned int i, j; for (i=0; i<pm->ngammas; ++i) for (j=0; j<pm->ngammas; ++j) if (i != j) { - gamma_transform_test(pm, colour_type, bit_depth, pm->interlace_type, - 1/pm->gammas[i], pm->gammas[j], bit_depth, speed, - pm->use_input_precision, 0 /*do not strip16*/); + gamma_transform_test(pm, colour_type, bit_depth, palette_number, + pm->interlace_type, 1/pm->gammas[i], pm->gammas[j], 0/*sBIT*/, + pm->use_input_precision, 0 /*do not scale16*/); if (fail(pm)) return; @@ -5766,55 +7422,41 @@ static void perform_gamma_transform_tests(png_modifier *pm, int speed) } } -static void perform_gamma_sbit_tests(png_modifier *pm, int speed) +static void perform_gamma_sbit_tests(png_modifier *pm) { png_byte sbit; /* The only interesting cases are colour and grayscale, alpha is ignored here - * for overall speed. Only bit depths 8 and 16 are tested. + * for overall speed. Only bit depths where sbit is less than the bit depth + * are tested. */ for (sbit=pm->sbitlow; sbit<(1<<READ_BDHI); ++sbit) { - unsigned int i, j; - - for (i=0; i<pm->ngammas; ++i) - { - for (j=0; j<pm->ngammas; ++j) - { - if (i != j) - { - if (sbit < 8) - { - gamma_transform_test(pm, 0, 8, pm->interlace_type, - 1/pm->gammas[i], pm->gammas[j], sbit, speed, - pm->use_input_precision_sbit, 0 /*strip16*/); - - if (fail(pm)) - return; + png_byte colour_type, bit_depth; + int npalette; - gamma_transform_test(pm, 2, 8, pm->interlace_type, - 1/pm->gammas[i], pm->gammas[j], sbit, speed, - pm->use_input_precision_sbit, 0 /*strip16*/); + colour_type = bit_depth = 0; + npalette = 0; - if (fail(pm)) - return; - } - -#ifdef DO_16BIT - gamma_transform_test(pm, 0, 16, pm->interlace_type, - 1/pm->gammas[i], pm->gammas[j], sbit, speed, - pm->use_input_precision_sbit, 0 /*strip16*/); + while (next_format(&colour_type, &bit_depth, &npalette)) + if ((colour_type & PNG_COLOR_MASK_ALPHA) == 0 && + ((colour_type == 3 && sbit < 8) || + (colour_type != 3 && sbit < bit_depth))) + { + unsigned int i; - if (fail(pm)) - return; + for (i=0; i<pm->ngammas; ++i) + { + unsigned int j; - gamma_transform_test(pm, 2, 16, pm->interlace_type, - 1/pm->gammas[i], pm->gammas[j], sbit, speed, - pm->use_input_precision_sbit, 0 /*strip16*/); + for (j=0; j<pm->ngammas; ++j) if (i != j) + { + gamma_transform_test(pm, colour_type, bit_depth, npalette, + pm->interlace_type, 1/pm->gammas[i], pm->gammas[j], + sbit, pm->use_input_precision_sbit, 0 /*scale16*/); if (fail(pm)) return; -#endif } } } @@ -5822,10 +7464,11 @@ static void perform_gamma_sbit_tests(png_modifier *pm, int speed) } /* Note that this requires a 16 bit source image but produces 8 bit output, so - * we only need the 16bit write support. + * we only need the 16bit write support, but the 16 bit images are only + * generated if DO_16BIT is defined. */ -#ifdef PNG_READ_16_TO_8_SUPPORTED -static void perform_gamma_strip16_tests(png_modifier *pm, int speed) +#ifdef DO_16BIT +static void perform_gamma_scale16_tests(png_modifier *pm) { # ifndef PNG_MAX_GAMMA_8 # define PNG_MAX_GAMMA_8 11 @@ -5846,30 +7489,30 @@ static void perform_gamma_strip16_tests(png_modifier *pm, int speed) if (i != j && fabs(pm->gammas[j]/pm->gammas[i]-1) >= PNG_GAMMA_THRESHOLD) { - gamma_transform_test(pm, 0, 16, pm->interlace_type, 1/pm->gammas[i], - pm->gammas[j], PNG_MAX_GAMMA_8, speed, - pm->use_input_precision_16to8, 1 /*strip16*/); + gamma_transform_test(pm, 0, 16, 0, pm->interlace_type, + 1/pm->gammas[i], pm->gammas[j], PNG_MAX_GAMMA_8, + pm->use_input_precision_16to8, 1 /*scale16*/); if (fail(pm)) return; - gamma_transform_test(pm, 2, 16, pm->interlace_type, 1/pm->gammas[i], - pm->gammas[j], PNG_MAX_GAMMA_8, speed, - pm->use_input_precision_16to8, 1 /*strip16*/); + gamma_transform_test(pm, 2, 16, 0, pm->interlace_type, + 1/pm->gammas[i], pm->gammas[j], PNG_MAX_GAMMA_8, + pm->use_input_precision_16to8, 1 /*scale16*/); if (fail(pm)) return; - gamma_transform_test(pm, 4, 16, pm->interlace_type, 1/pm->gammas[i], - pm->gammas[j], PNG_MAX_GAMMA_8, speed, - pm->use_input_precision_16to8, 1 /*strip16*/); + gamma_transform_test(pm, 4, 16, 0, pm->interlace_type, + 1/pm->gammas[i], pm->gammas[j], PNG_MAX_GAMMA_8, + pm->use_input_precision_16to8, 1 /*scale16*/); if (fail(pm)) return; - gamma_transform_test(pm, 6, 16, pm->interlace_type, 1/pm->gammas[i], - pm->gammas[j], PNG_MAX_GAMMA_8, speed, - pm->use_input_precision_16to8, 1 /*strip16*/); + gamma_transform_test(pm, 6, 16, 0, pm->interlace_type, + 1/pm->gammas[i], pm->gammas[j], PNG_MAX_GAMMA_8, + pm->use_input_precision_16to8, 1 /*scale16*/); if (fail(pm)) return; @@ -5879,11 +7522,201 @@ static void perform_gamma_strip16_tests(png_modifier *pm, int speed) } #endif /* 16 to 8 bit conversion */ +#if defined PNG_READ_BACKGROUND_SUPPORTED ||\ + defined PNG_READ_ALPHA_MODE_SUPPORTED +static void gamma_composition_test(png_modifier *pm, + PNG_CONST png_byte colour_type, PNG_CONST png_byte bit_depth, + PNG_CONST int palette_number, + PNG_CONST int interlace_type, PNG_CONST double file_gamma, + PNG_CONST double screen_gamma, + PNG_CONST int use_input_precision, PNG_CONST int do_background, + PNG_CONST int expand_16) +{ + size_t pos = 0; + png_const_charp base; + double bg; + char name[128]; + png_color_16 background; + + /* Make up a name and get an appropriate background gamma value. */ + switch (do_background) + { + default: + base = ""; + bg = 4; /* should not be used */ + break; + case PNG_BACKGROUND_GAMMA_SCREEN: + base = " bckg(Screen):"; + bg = 1/screen_gamma; + break; + case PNG_BACKGROUND_GAMMA_FILE: + base = " bckg(File):"; + bg = file_gamma; + break; + case PNG_BACKGROUND_GAMMA_UNIQUE: + base = " bckg(Unique):"; + /* This tests the handling of a unique value, the math is such that the + * value tends to be <1, but is neither screen nor file (even if they + * match!) + */ + bg = (file_gamma + screen_gamma) / 3; + break; +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED + case ALPHA_MODE_OFFSET + PNG_ALPHA_PNG: + base = " alpha(PNG)"; + bg = 4; /* should not be used */ + break; + case ALPHA_MODE_OFFSET + PNG_ALPHA_STANDARD: + base = " alpha(Porter-Duff)"; + bg = 4; /* should not be used */ + break; + case ALPHA_MODE_OFFSET + PNG_ALPHA_OPTIMIZED: + base = " alpha(Optimized)"; + bg = 4; /* should not be used */ + break; + case ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN: + base = " alpha(Broken)"; + bg = 4; /* should not be used */ + break; +#endif + } + + /* Use random background values - the background is always presented in the + * output space (8 or 16 bit components). + */ + if (expand_16 || bit_depth == 16) + { + png_uint_32 r = random_32(); + + background.red = (png_uint_16)r; + background.green = (png_uint_16)(r >> 16); + r = random_32(); + background.blue = (png_uint_16)r; + background.gray = (png_uint_16)(r >> 16); + } + + else /* 8 bit colors */ + { + png_uint_32 r = random_32(); + + background.red = (png_byte)r; + background.green = (png_byte)(r >> 8); + background.blue = (png_byte)(r >> 16); + background.gray = (png_byte)(r >> 24); + } + + background.index = 193; /* rgb(193,193,193) to detect errors */ + if (!(colour_type & PNG_COLOR_MASK_COLOR)) + { + /* Grayscale input, we do not convert to RGB (TBD), so we must set the + * background to gray - else libpng seems to fail. + */ + background.red = background.green = background.blue = background.gray; + } + + pos = safecat(name, sizeof name, pos, "gamma "); + pos = safecatd(name, sizeof name, pos, file_gamma, 3); + pos = safecat(name, sizeof name, pos, "->"); + pos = safecatd(name, sizeof name, pos, screen_gamma, 3); + + pos = safecat(name, sizeof name, pos, base); + if (do_background < ALPHA_MODE_OFFSET) + { + /* Include the background color and gamma in the name: */ + pos = safecat(name, sizeof name, pos, "("); + /* This assumes no expand gray->rgb - the current code won't handle that! + */ + if (colour_type & PNG_COLOR_MASK_COLOR) + { + pos = safecatn(name, sizeof name, pos, background.red); + pos = safecat(name, sizeof name, pos, ","); + pos = safecatn(name, sizeof name, pos, background.green); + pos = safecat(name, sizeof name, pos, ","); + pos = safecatn(name, sizeof name, pos, background.blue); + } + else + pos = safecatn(name, sizeof name, pos, background.gray); + pos = safecat(name, sizeof name, pos, ")^"); + pos = safecatd(name, sizeof name, pos, bg, 3); + } + + gamma_test(pm, colour_type, bit_depth, palette_number, interlace_type, + file_gamma, screen_gamma, 0/*sBIT*/, 0, name, use_input_precision, + 0/*strip 16*/, expand_16, do_background, &background, bg); +} + + +static void +perform_gamma_composition_tests(png_modifier *pm, int do_background, + int expand_16) +{ + png_byte colour_type = 0; + png_byte bit_depth = 0; + int palette_number = 0; + + /* Skip the non-alpha cases - there is no setting of a transparency colour at + * present. + */ + while (next_format(&colour_type, &bit_depth, &palette_number)) + if ((colour_type & PNG_COLOR_MASK_ALPHA) != 0) + { + unsigned int i, j; + + /* Don't skip the i==j case here - it's relevant. */ + for (i=0; i<pm->ngammas; ++i) for (j=0; j<pm->ngammas; ++j) + { + gamma_composition_test(pm, colour_type, bit_depth, palette_number, + pm->interlace_type, 1/pm->gammas[i], pm->gammas[j], + pm->use_input_precision, do_background, expand_16); + + if (fail(pm)) + return; + } + } +} +#endif /* READ_BACKGROUND || READ_ALPHA_MODE */ + +static void +init_gamma_errors(png_modifier *pm) +{ + pm->error_gray_2 = pm->error_gray_4 = pm->error_gray_8 = 0; + pm->error_color_8 = 0; + pm->error_indexed = 0; + pm->error_gray_16 = pm->error_color_16 = 0; +} + +static void +summarize_gamma_errors(png_modifier *pm, png_const_charp who, int low_bit_depth) +{ + if (who) + printf("Gamma correction with %s:\n", who); + + if (low_bit_depth) + { + printf(" 2 bit gray: %.5f\n", pm->error_gray_2); + printf(" 4 bit gray: %.5f\n", pm->error_gray_4); + printf(" 8 bit gray: %.5f\n", pm->error_gray_8); + printf(" 8 bit color: %.5f\n", pm->error_color_8); + printf(" indexed: %.5f\n", pm->error_indexed); + } + +#ifdef DO_16BIT + printf(" 16 bit gray: %.5f\n", pm->error_gray_16); + printf(" 16 bit color: %.5f\n", pm->error_color_16); +#endif +} + static void -perform_gamma_test(png_modifier *pm, int speed, int summary) +perform_gamma_test(png_modifier *pm, int summary) { + /*TODO: remove this*/ + /* Save certain values for the temporary overrides below. */ + unsigned int calculations_use_input_precision = + pm->calculations_use_input_precision; + double maxout8 = pm->maxout8; + /* First some arbitrary no-transform tests: */ - if (!speed && pm->test_gamma_threshold) + if (!pm->this.speed && pm->test_gamma_threshold) { perform_gamma_threshold_tests(pm); @@ -5894,7 +7727,15 @@ perform_gamma_test(png_modifier *pm, int speed, int summary) /* Now some real transforms. */ if (pm->test_gamma_transform) { - perform_gamma_transform_tests(pm, speed); + init_gamma_errors(pm); + /*TODO: remove this. Necessary because the current libpng + * implementation works in 8 bits: + */ + if (pm->test_gamma_expand16) + pm->calculations_use_input_precision = 1; + perform_gamma_transform_tests(pm); + if (!calculations_use_input_precision) + pm->calculations_use_input_precision = 0; if (summary) { @@ -5911,50 +7752,26 @@ perform_gamma_test(png_modifier *pm, int speed, int summary) printf("For performance reasons the value for 16 bit formats\n"); printf("increases when the image file includes an sBIT chunk.\n\n"); - printf(" 2 bit gray: %.5f\n", pm->error_gray_2); - printf(" 4 bit gray: %.5f\n", pm->error_gray_4); - printf(" 8 bit gray: %.5f\n", pm->error_gray_8); - printf(" 8 bit color: %.5f\n", pm->error_color_8); -#ifdef DO_16BIT - printf(" 16 bit gray: %.5f\n", pm->error_gray_16); - printf(" 16 bit color: %.5f\n", pm->error_color_16); -#endif + summarize_gamma_errors(pm, 0/*who*/, 1); } } /* The sbit tests produce much larger errors: */ if (pm->test_gamma_sbit) { - pm->error_gray_2 = pm->error_gray_4 = pm->error_gray_8 = - pm->error_gray_16 = pm->error_color_8 = pm->error_color_16 = 0; - perform_gamma_sbit_tests(pm, speed); + init_gamma_errors(pm); + perform_gamma_sbit_tests(pm); if (summary) - { - printf("Gamma correction with sBIT:\n"); - - if (pm->sbitlow < 8U) - { - printf(" 2 bit gray: %.5f\n", pm->error_gray_2); - printf(" 4 bit gray: %.5f\n", pm->error_gray_4); - printf(" 8 bit gray: %.5f\n", pm->error_gray_8); - printf(" 8 bit color: %.5f\n", pm->error_color_8); - } - - #ifdef DO_16BIT - printf(" 16 bit gray: %.5f\n", pm->error_gray_16); - printf(" 16 bit color: %.5f\n", pm->error_color_16); - #endif - } + summarize_gamma_errors(pm, "sBIT", pm->sbitlow < 8U); } -#ifdef PNG_READ_16_TO_8_SUPPORTED - if (pm->test_gamma_strip16) +#ifdef DO_16BIT /* Should be READ_16BIT_SUPPORTED */ + if (pm->test_gamma_scale16) { /* The 16 to 8 bit strip operations: */ - pm->error_gray_2 = pm->error_gray_4 = pm->error_gray_8 = - pm->error_gray_16 = pm->error_color_8 = pm->error_color_16 = 0; - perform_gamma_strip16_tests(pm, speed); + init_gamma_errors(pm); + perform_gamma_scale16_tests(pm); if (summary) { @@ -5964,7 +7781,57 @@ perform_gamma_test(png_modifier *pm, int speed, int summary) } } #endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED + if (pm->test_gamma_background) + { + init_gamma_errors(pm); + + /*TODO: remove this. Necessary because the current libpng + * implementation works in 8 bits: + */ + if (pm->test_gamma_expand16) + { + pm->calculations_use_input_precision = 1; + pm->maxout8 = .499; /* because the 16 bit background is smashed */ + } + perform_gamma_composition_tests(pm, PNG_BACKGROUND_GAMMA_UNIQUE, + pm->test_gamma_expand16); + if (!calculations_use_input_precision) + pm->calculations_use_input_precision = 0; + pm->maxout8 = maxout8; + + if (summary) + summarize_gamma_errors(pm, "background", 1); + } +#endif + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED + if (pm->test_gamma_alpha_mode) + { + int do_background; + + init_gamma_errors(pm); + + /*TODO: remove this. Necessary because the current libpng + * implementation works in 8 bits: + */ + if (pm->test_gamma_expand16) + pm->calculations_use_input_precision = 1; + for (do_background = ALPHA_MODE_OFFSET + PNG_ALPHA_STANDARD; + do_background <= ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN && !fail(pm); + ++do_background) + perform_gamma_composition_tests(pm, do_background, + pm->test_gamma_expand16); + if (!calculations_use_input_precision) + pm->calculations_use_input_precision = 0; + + if (summary) + summarize_gamma_errors(pm, "alpha mode", 1); + } +#endif } +#endif /* PNG_READ_GAMMA_SUPPORTED */ /* INTERLACE MACRO VALIDATION */ /* This is copied verbatim from the specification, it is simply the pass @@ -6316,6 +8183,7 @@ perform_interlace_macro_validation(void) int main(int argc, PNG_CONST char **argv) { volatile int summary = 1; /* Print the error summary at the end */ + volatile int memstats = 0; /* Print memory statistics at the end */ /* Create the given output file on success: */ PNG_CONST char *volatile touch = NULL; @@ -6328,24 +8196,24 @@ int main(int argc, PNG_CONST char **argv) static double gammas[]={2.2, 1.0, 2.2/1.45, 1.8, 1.5, 2.4, 2.5, 2.62, 2.9}; + /* This records the command and arguments: */ + size_t cp = 0; + char command[1024]; + png_modifier pm; context(&pm.this, fault); modifier_init(&pm); /* Preallocate the image buffer, because we know how big it needs to be, - * note that, for testing purposes, it is deliberately mis-aligned. + * note that, for testing purposes, it is deliberately mis-aligned by tag + * bytes either side. All rows have an additional five bytes of padding for + * overwrite checking. */ - pm.this.image = malloc(2*TRANSFORM_IMAGEMAX+1); + store_ensure_image(&pm.this, NULL, 2, TRANSFORM_ROWMAX, TRANSFORM_HEIGHTMAX); - if (pm.this.image != NULL) - { - /* Ignore OOM at this point - the 'ensure' routine above will allocate - * the array appropriately. - */ - ++(pm.this.image); - pm.this.cb_image = 2*TRANSFORM_IMAGEMAX; - } + /* Don't give argv[0], it's normally some horrible libtool string: */ + cp = safecat(command, sizeof command, cp, "pngvalid"); /* Default to error on warning: */ pm.this.treat_warnings_as_errors = 1; @@ -6354,7 +8222,13 @@ int main(int argc, PNG_CONST char **argv) pm.gammas = gammas; pm.ngammas = 0; /* default to off */ pm.sbitlow = 8U; /* because libpng doesn't do sBIT below 8! */ - pm.use_input_precision_16to8 = 1U; /* Because of the way libpng does it */ + /* The following allows results to pass if they correspond to anything in the + * transformed range [input-.5,input+.5]; this is is required because of the + * way libpng treates the 16_TO_8 flag when building the gamma tables. + * + * TODO: review this + */ + pm.use_input_precision_16to8 = 1U; /* Some default values (set the behavior for 'make check' here). * These values simply control the maximum error permitted in the gamma @@ -6365,9 +8239,11 @@ int main(int argc, PNG_CONST char **argv) */ pm.maxout8 = .1; /* Arithmetic error in *encoded* value */ pm.maxabs8 = .00005; /* 1/20000 */ + pm.maxcalc8 = .004; /* +/-1 in 8 bits for compose errors */ pm.maxpc8 = .499; /* I.e., .499% fractional error */ pm.maxout16 = .499; /* Error in *encoded* value */ pm.maxabs16 = .00005;/* 1/20000 */ + pm.maxcalc16 =.000015;/* +/-1 in 16 bits for compose errors */ /* NOTE: this is a reasonable perceptual limit. We assume that humans can * perceive light level differences of 1% over a 100:1 range, so we need to @@ -6382,7 +8258,13 @@ int main(int argc, PNG_CONST char **argv) /* Now parse the command line options. */ while (--argc >= 1) { - if (strcmp(*++argv, "-v") == 0) + int catmore = 0; /* Set if the argument has an argument. */ + + /* Record each argument for posterity: */ + cp = safecat(command, sizeof command, cp, " "); + cp = safecat(command, sizeof command, cp, *++argv); + + if (strcmp(*argv, "-v") == 0) pm.this.verbose = 1; else if (strcmp(*argv, "-l") == 0) @@ -6396,7 +8278,10 @@ int main(int argc, PNG_CONST char **argv) else if (strcmp(*argv, "--speed") == 0) pm.this.speed = 1, pm.ngammas = (sizeof gammas)/(sizeof gammas[0]), - pm.test_standard = 0; + pm.test_standard = 0, summary = 0; + + else if (strcmp(*argv, "--memory") == 0) + memstats = 1; else if (strcmp(*argv, "--size") == 0) pm.test_size = 1; @@ -6416,6 +8301,7 @@ int main(int argc, PNG_CONST char **argv) else if (strcmp(*argv, "--notransform") == 0) pm.test_transform = 0; +#ifdef PNG_READ_TRANSFORMS_SUPPORTED else if (strncmp(*argv, "--transform-disable=", sizeof "--transform-disable") == 0) { @@ -6429,6 +8315,7 @@ int main(int argc, PNG_CONST char **argv) pm.test_transform = 1; transform_enable(*argv + sizeof "--transform-enable"); } +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ else if (strcmp(*argv, "--gamma") == 0) { @@ -6437,7 +8324,9 @@ int main(int argc, PNG_CONST char **argv) pm.test_gamma_threshold = 1; pm.test_gamma_transform = 1; pm.test_gamma_sbit = 1; - pm.test_gamma_strip16 = 1; + pm.test_gamma_scale16 = 1; + pm.test_gamma_background = 1; + pm.test_gamma_alpha_mode = 1; } else if (strcmp(*argv, "--nogamma") == 0) @@ -6462,10 +8351,31 @@ int main(int argc, PNG_CONST char **argv) pm.test_gamma_sbit = 0; else if (strcmp(*argv, "--gamma-16-to-8") == 0) - pm.ngammas = 2U, pm.test_gamma_strip16 = 1; + pm.ngammas = 2U, pm.test_gamma_scale16 = 1; else if (strcmp(*argv, "--nogamma-16-to-8") == 0) - pm.test_gamma_strip16 = 0; + pm.test_gamma_scale16 = 0; + + else if (strcmp(*argv, "--gamma-background") == 0) + pm.ngammas = 2U, pm.test_gamma_background = 1; + + else if (strcmp(*argv, "--nogamma-background") == 0) + pm.test_gamma_background = 0; + + else if (strcmp(*argv, "--gamma-alpha-mode") == 0) + pm.ngammas = 2U, pm.test_gamma_alpha_mode = 1; + + else if (strcmp(*argv, "--nogamma-alpha-mode") == 0) + pm.test_gamma_alpha_mode = 0; + + else if (strcmp(*argv, "--expand16") == 0) + pm.test_gamma_expand16 = 1; + + else if (strcmp(*argv, "--noexpand16") == 0) + pm.test_gamma_expand16 = 0; + + else if (strcmp(*argv, "--more-gammas") == 0) + pm.ngammas = 3U; else if (strcmp(*argv, "--all-gammas") == 0) pm.ngammas = (sizeof gammas)/(sizeof gammas[0]); @@ -6476,32 +8386,51 @@ int main(int argc, PNG_CONST char **argv) else if (strcmp(*argv, "--interlace") == 0) pm.interlace_type = PNG_INTERLACE_ADAM7; - else if (argc >= 1 && strcmp(*argv, "--sbitlow") == 0) - --argc, pm.sbitlow = (png_byte)atoi(*++argv); + else if (strcmp(*argv, "--use-input-precision") == 0) + pm.use_input_precision = 1; + + else if (strcmp(*argv, "--calculations-use-input-precision") == 0) + pm.calculations_use_input_precision = 1; + + else if (strcmp(*argv, "--assume-16-bit-calculations") == 0) + pm.assume_16_bit_calculations = 1; - else if (argc >= 1 && strcmp(*argv, "--touch") == 0) - --argc, touch = *++argv; + else if (strcmp(*argv, "--calculations-follow-bit-depth") == 0) + pm.calculations_use_input_precision = + pm.assume_16_bit_calculations = 0; - else if (argc >= 1 && strncmp(*argv, "--max", 4) == 0) + else if (argc > 1 && strcmp(*argv, "--sbitlow") == 0) + --argc, pm.sbitlow = (png_byte)atoi(*++argv), catmore = 1; + + else if (argc > 1 && strcmp(*argv, "--touch") == 0) + --argc, touch = *++argv, catmore = 1; + + else if (argc > 1 && strncmp(*argv, "--max", 5) == 0) { --argc; - if (strcmp(4+*argv, "abs8") == 0) + if (strcmp(5+*argv, "abs8") == 0) pm.maxabs8 = atof(*++argv); - else if (strcmp(4+*argv, "abs16") == 0) + else if (strcmp(5+*argv, "abs16") == 0) pm.maxabs16 = atof(*++argv); - else if (strcmp(4+*argv, "out8") == 0) + else if (strcmp(5+*argv, "calc8") == 0) + pm.maxcalc8 = atof(*++argv); + + else if (strcmp(5+*argv, "calc16") == 0) + pm.maxcalc16 = atof(*++argv); + + else if (strcmp(5+*argv, "out8") == 0) pm.maxout8 = atof(*++argv); - else if (strcmp(4+*argv, "out16") == 0) + else if (strcmp(5+*argv, "out16") == 0) pm.maxout16 = atof(*++argv); - else if (strcmp(4+*argv, "pc8") == 0) + else if (strcmp(5+*argv, "pc8") == 0) pm.maxpc8 = atof(*++argv); - else if (strcmp(4+*argv, "pc16") == 0) + else if (strcmp(5+*argv, "pc16") == 0) pm.maxpc16 = atof(*++argv); else @@ -6509,13 +8438,27 @@ int main(int argc, PNG_CONST char **argv) fprintf(stderr, "pngvalid: %s: unknown 'max' option\n", *argv); exit(1); } + + catmore = 1; } + else if (strcmp(*argv, "--log8") == 0) + --argc, pm.log8 = atof(*++argv), catmore = 1; + + else if (strcmp(*argv, "--log16") == 0) + --argc, pm.log16 = atof(*++argv), catmore = 1; + else { fprintf(stderr, "pngvalid: %s: unknown argument\n", *argv); exit(1); } + + if (catmore) /* consumed an extra *argv */ + { + cp = safecat(command, sizeof command, cp, " "); + cp = safecat(command, sizeof command, cp, *argv); + } } /* If pngvalid is run with no arguments default to a reasonable set of the @@ -6524,29 +8467,39 @@ int main(int argc, PNG_CONST char **argv) if (pm.test_standard == 0 && pm.test_size == 0 && pm.test_transform == 0 && pm.ngammas == 0) { + /* Make this do all the tests done in the test shell scripts with the same + * parameters, where possible. The limitation is that all the progressive + * read and interlace stuff has to be done in separate runs, so only the + * basic 'standard' and 'size' tests are done. + */ pm.test_standard = 1; pm.test_size = 1; pm.test_transform = 1; - pm.ngammas = 3U; + pm.ngammas = 2U; } if (pm.ngammas > 0 && pm.test_gamma_threshold == 0 && pm.test_gamma_transform == 0 && - pm.test_gamma_sbit == 0 && pm.test_gamma_strip16 == 0) + pm.test_gamma_sbit == 0 && pm.test_gamma_scale16 == 0 && + pm.test_gamma_background == 0 && pm.test_gamma_alpha_mode == 0) { pm.test_gamma_threshold = 1; pm.test_gamma_transform = 1; pm.test_gamma_sbit = 1; - pm.test_gamma_strip16 = 1; + pm.test_gamma_scale16 = 1; + pm.test_gamma_background = 1; + pm.test_gamma_alpha_mode = 1; } - + else if (pm.ngammas == 0) { /* Nothing to test so turn everything off: */ pm.test_gamma_threshold = 0; pm.test_gamma_transform = 0; pm.test_gamma_sbit = 0; - pm.test_gamma_strip16 = 0; + pm.test_gamma_scale16 = 0; + pm.test_gamma_background = 0; + pm.test_gamma_alpha_mode = 0; } Try @@ -6558,6 +8511,7 @@ int main(int argc, PNG_CONST char **argv) if (pm.test_standard) { perform_interlace_macro_validation(); + perform_formatting_test(&pm.this); perform_standard_test(&pm); perform_error_test(&pm); } @@ -6569,13 +8523,16 @@ int main(int argc, PNG_CONST char **argv) perform_size_test(&pm); } +#ifdef PNG_READ_TRANSFORMS_SUPPORTED /* Combinatorial transforms: */ if (pm.test_transform) perform_transform_test(&pm); +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ +#ifdef PNG_READ_GAMMA_SUPPORTED if (pm.ngammas > 0) - perform_gamma_test(&pm, pm.this.speed != 0, - summary && !pm.this.speed); + perform_gamma_test(&pm, summary); +#endif } Catch(fault) @@ -6591,18 +8548,22 @@ int main(int argc, PNG_CONST char **argv) exit(1); } - if (summary && !pm.this.speed) + if (summary) { - printf("Results using %s point arithmetic %s\n", + printf("%s: %s (%s point arithmetic)\n", + (pm.this.nerrors || (pm.this.treat_warnings_as_errors && + pm.this.nwarnings)) ? "FAIL" : "PASS", + command, #if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || PNG_LIBPNG_VER < 10500 - "floating", + "floating" #else - "fixed", + "fixed" #endif - (pm.this.nerrors || (pm.this.treat_warnings_as_errors && - pm.this.nwarnings)) ? "(errors)" : (pm.this.nwarnings ? - "(warnings)" : "(no errors or warnings)") - ); + ); + } + + if (memstats) + { printf("Allocated memory statistics (in bytes):\n" "\tread %lu maximum single, %lu peak, %lu total\n" "\twrite %lu maximum single, %lu peak, %lu total\n", diff --git a/src/3rdparty/libpng/pngwrite.c b/src/3rdparty/libpng/pngwrite.c index d90f449..d1af9e8 100644 --- a/src/3rdparty/libpng/pngwrite.c +++ b/src/3rdparty/libpng/pngwrite.c @@ -1,7 +1,7 @@ /* pngwrite.c - general routines to write a PNG file * - * Last changed in libpng 1.5.1 [February 3, 2011] + * Last changed in libpng 1.5.4 [July 7, 2011] * Copyright (c) 1998-2011 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -99,8 +99,10 @@ png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr) int keep = png_handle_as_unknown(png_ptr, up->name); if (keep != PNG_HANDLE_CHUNK_NEVER && - up->location && !(up->location & PNG_HAVE_PLTE) && + up->location && + !(up->location & PNG_HAVE_PLTE) && !(up->location & PNG_HAVE_IDAT) && + !(up->location & PNG_AFTER_IDAT) && ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) { @@ -273,8 +275,10 @@ png_write_info(png_structp png_ptr, png_infop info_ptr) { int keep = png_handle_as_unknown(png_ptr, up->name); if (keep != PNG_HANDLE_CHUNK_NEVER && - up->location && (up->location & PNG_HAVE_PLTE) && + up->location && + (up->location & PNG_HAVE_PLTE) && !(up->location & PNG_HAVE_IDAT) && + !(up->location & PNG_AFTER_IDAT) && ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) { @@ -380,7 +384,8 @@ png_write_end(png_structp png_ptr, png_infop info_ptr) { int keep = png_handle_as_unknown(png_ptr, up->name); if (keep != PNG_HANDLE_CHUNK_NEVER && - up->location && (up->location & PNG_AFTER_IDAT) && + up->location && + (up->location & PNG_AFTER_IDAT) && ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) { @@ -462,10 +467,9 @@ png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, png_structp png_ptr; #ifdef PNG_SETJMP_SUPPORTED #ifdef USE_FAR_KEYWORD - jmp_buf png_jmpbuf; + jmp_buf tmp_jmpbuf; #endif #endif - int i; png_debug(1, "in png_create_write_struct"); @@ -489,12 +493,12 @@ png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, encounter a png_error() will longjmp here. Since the jmpbuf is then meaningless we abort instead of returning. */ #ifdef USE_FAR_KEYWORD - if (setjmp(png_jmpbuf)) + if (setjmp(tmp_jmpbuf)) #else if (setjmp(png_jmpbuf(png_ptr))) /* sets longjmp to match setjmp */ #endif #ifdef USE_FAR_KEYWORD - png_memcpy(png_jmpbuf(png_ptr), png_jmpbuf, png_sizeof(jmp_buf)); + png_memcpy(png_jmpbuf(png_ptr), tmp_jmpbuf, png_sizeof(jmp_buf)); #endif PNG_ABORT(); #endif @@ -504,49 +508,8 @@ png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, #endif /* PNG_USER_MEM_SUPPORTED */ png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); - if (user_png_ver) - { - i = 0; - do - { - if (user_png_ver[i] != png_libpng_ver[i]) - png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; - } while (png_libpng_ver[i++]); - } - - if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) - { - /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so - * we must recompile any applications that use any older library version. - * For versions after libpng 1.0, we will be compatible, so we need - * only check the first digit. - */ - if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || - (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || - (user_png_ver[0] == '0' && user_png_ver[2] < '9')) - { -#ifdef PNG_CONSOLE_IO_SUPPORTED - char msg[80]; - - if (user_png_ver) - { - png_snprintf2(msg, 80, - "Application built with libpng-%.20s" - " but running with %.20s", - user_png_ver, - png_libpng_ver); - png_warning(png_ptr, msg); - } -#else - png_warning(png_ptr, - "Incompatible libpng version in application and library"); -#endif -#ifdef PNG_ERROR_NUMBERS_SUPPORTED - png_ptr->flags = 0; -#endif - png_cleanup_needed = 1; - } - } + if (!png_user_version_check(png_ptr, user_png_ver)) + png_cleanup_needed = 1; /* Initialize zbuf - compression buffer */ png_ptr->zbuf_size = PNG_ZBUF_SIZE; @@ -805,9 +768,11 @@ png_write_row(png_structp png_ptr, png_const_bytep row) } #endif +#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED /* Handle other transformations */ if (png_ptr->transformations) png_do_write_transformations(png_ptr); +#endif #ifdef PNG_MNG_FEATURES_SUPPORTED /* Write filter_method 64 (intrapixel differencing) only if @@ -884,8 +849,6 @@ png_write_flush(png_structp png_ptr) { /* Write the IDAT and reset the zlib output buffer */ png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; wrote_IDAT = 1; } } while (wrote_IDAT == 1); @@ -896,8 +859,6 @@ png_write_flush(png_structp png_ptr) /* Write the IDAT and reset the zlib output buffer */ png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size - png_ptr->zstream.avail_out); - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; } png_ptr->flush_rows = 0; png_flush(png_ptr); @@ -983,7 +944,9 @@ png_write_destroy(png_structp png_ptr) jmp_buf tmp_jmp; /* Save jump buffer */ #endif png_error_ptr error_fn; +#ifdef PNG_WARNINGS_SUPPORTED png_error_ptr warning_fn; +#endif png_voidp error_ptr; #ifdef PNG_USER_MEM_SUPPORTED png_free_ptr free_fn; @@ -992,7 +955,8 @@ png_write_destroy(png_structp png_ptr) png_debug(1, "in png_write_destroy"); /* Free any memory zlib uses */ - deflateEnd(&png_ptr->zstream); + if (png_ptr->zlib_state != PNG_ZLIB_UNINITIALIZED) + deflateEnd(&png_ptr->zstream); /* Free our memory. png_free checks NULL for us. */ png_free(png_ptr, png_ptr->zbuf); @@ -1005,10 +969,6 @@ png_write_destroy(png_structp png_ptr) png_free(png_ptr, png_ptr->paeth_row); #endif -#ifdef PNG_TIME_RFC1123_SUPPORTED - png_free(png_ptr, png_ptr->time_buffer); -#endif - #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* Use this to save a little code space, it doesn't free the filter_costs */ png_reset_filter_heuristics(png_ptr); @@ -1018,11 +978,13 @@ png_write_destroy(png_structp png_ptr) #ifdef PNG_SETJMP_SUPPORTED /* Reset structure */ - png_memcpy(tmp_jmp, png_ptr->png_jmpbuf, png_sizeof(jmp_buf)); + png_memcpy(tmp_jmp, png_ptr->longjmp_buffer, png_sizeof(jmp_buf)); #endif error_fn = png_ptr->error_fn; +#ifdef PNG_WARNINGS_SUPPORTED warning_fn = png_ptr->warning_fn; +#endif error_ptr = png_ptr->error_ptr; #ifdef PNG_USER_MEM_SUPPORTED free_fn = png_ptr->free_fn; @@ -1031,14 +993,16 @@ png_write_destroy(png_structp png_ptr) png_memset(png_ptr, 0, png_sizeof(png_struct)); png_ptr->error_fn = error_fn; +#ifdef PNG_WARNINGS_SUPPORTED png_ptr->warning_fn = warning_fn; +#endif png_ptr->error_ptr = error_ptr; #ifdef PNG_USER_MEM_SUPPORTED png_ptr->free_fn = free_fn; #endif #ifdef PNG_SETJMP_SUPPORTED - png_memcpy(png_ptr->png_jmpbuf, tmp_jmp, png_sizeof(jmp_buf)); + png_memcpy(png_ptr->longjmp_buffer, tmp_jmp, png_sizeof(jmp_buf)); #endif } @@ -1177,7 +1141,7 @@ png_set_filter(png_structp png_ptr, int method, int filters) * better compression. */ #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* GRR 970116 */ -/* Conveneince reset API. */ +/* Convenience reset API. */ static void png_reset_filter_heuristics(png_structp png_ptr) { @@ -1451,6 +1415,9 @@ png_set_compression_strategy(png_structp png_ptr, int strategy) png_ptr->zlib_strategy = strategy; } +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ void PNGAPI png_set_compression_window_bits(png_structp png_ptr, int window_bits) { @@ -1491,6 +1458,89 @@ png_set_compression_method(png_structp png_ptr, int method) png_ptr->zlib_method = method; } +/* The following were added to libpng-1.5.4 */ +#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +void PNGAPI +png_set_text_compression_level(png_structp png_ptr, int level) +{ + png_debug(1, "in png_set_text_compression_level"); + + if (png_ptr == NULL) + return; + + png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_LEVEL; + png_ptr->zlib_text_level = level; +} + +void PNGAPI +png_set_text_compression_mem_level(png_structp png_ptr, int mem_level) +{ + png_debug(1, "in png_set_text_compression_mem_level"); + + if (png_ptr == NULL) + return; + + png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_MEM_LEVEL; + png_ptr->zlib_text_mem_level = mem_level; +} + +void PNGAPI +png_set_text_compression_strategy(png_structp png_ptr, int strategy) +{ + png_debug(1, "in png_set_text_compression_strategy"); + + if (png_ptr == NULL) + return; + + png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_STRATEGY; + png_ptr->zlib_text_strategy = strategy; +} + +/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a + * smaller value of window_bits if it can do so safely. + */ +void PNGAPI +png_set_text_compression_window_bits(png_structp png_ptr, int window_bits) +{ + if (png_ptr == NULL) + return; + + if (window_bits > 15) + png_warning(png_ptr, "Only compression windows <= 32k supported by PNG"); + + else if (window_bits < 8) + png_warning(png_ptr, "Only compression windows >= 256 supported by PNG"); + +#ifndef WBITS_8_OK + /* Avoid libpng bug with 256-byte windows */ + if (window_bits == 8) + { + png_warning(png_ptr, "Text compression window is being reset to 512"); + window_bits = 9; + } + +#endif + png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_WINDOW_BITS; + png_ptr->zlib_text_window_bits = window_bits; +} + +void PNGAPI +png_set_text_compression_method(png_structp png_ptr, int method) +{ + png_debug(1, "in png_set_text_compression_method"); + + if (png_ptr == NULL) + return; + + if (method != 8) + png_warning(png_ptr, "Only compression method 8 is supported by PNG"); + + png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_METHOD; + png_ptr->zlib_text_method = method; +} +#endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */ +/* end of API added to libpng-1.5.4 */ + void PNGAPI png_set_write_status_fn(png_structp png_ptr, png_write_status_ptr write_row_fn) { @@ -1557,7 +1607,7 @@ png_write_png(png_structp png_ptr, png_infop info_ptr, #endif #ifdef PNG_WRITE_FILLER_SUPPORTED - /* Pack XRGB/RGBX/ARGB/RGBA into * RGB (4 channels -> 3 channels) */ + /* Pack XRGB/RGBX/ARGB/RGBA into RGB (4 channels -> 3 channels) */ if (transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER) png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); diff --git a/src/3rdparty/libpng/pngwtran.c b/src/3rdparty/libpng/pngwtran.c index 115ca37..124d708 100644 --- a/src/3rdparty/libpng/pngwtran.c +++ b/src/3rdparty/libpng/pngwtran.c @@ -1,7 +1,7 @@ /* pngwtran.c - transforms the data in a row for PNG writers * - * Last changed in libpng 1.5.0 [January 6, 2011] + * Last changed in libpng 1.5.4 [July 7, 2011] * Copyright (c) 1998-2011 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -15,6 +15,7 @@ #ifdef PNG_WRITE_SUPPORTED +#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED /* Transform the data according to the user's wishes. The order of * transformations is significant. */ @@ -44,8 +45,8 @@ png_do_write_transformations(png_structp png_ptr) #ifdef PNG_WRITE_FILLER_SUPPORTED if (png_ptr->transformations & PNG_FILLER) - png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, - png_ptr->flags); + png_do_strip_channel(&(png_ptr->row_info), png_ptr->row_buf + 1, + !(png_ptr->flags & PNG_FLAG_FILLER_AFTER)); #endif #ifdef PNG_WRITE_PACKSWAP_SUPPORTED @@ -563,6 +564,7 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) } } #endif +#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */ #ifdef PNG_MNG_FEATURES_SUPPORTED /* Undoes intrapixel differencing */ diff --git a/src/3rdparty/libpng/pngwutil.c b/src/3rdparty/libpng/pngwutil.c index 2c35785..3ae5ed4 100644 --- a/src/3rdparty/libpng/pngwutil.c +++ b/src/3rdparty/libpng/pngwutil.c @@ -1,7 +1,7 @@ /* pngwutil.c - utilities to write a PNG file * - * Last changed in libpng 1.5.0 [January 6, 2011] + * Last changed in libpng 1.5.4 [July 7, 2011] * Copyright (c) 1998-2011 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -192,7 +192,149 @@ png_write_chunk_end(png_structp png_ptr) png_write_data(png_ptr, buf, (png_size_t)4); } -#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_iCCP_SUPPORTED) +/* Initialize the compressor for the appropriate type of compression. */ +static void +png_zlib_claim(png_structp png_ptr, png_uint_32 state) +{ + if (!(png_ptr->zlib_state & PNG_ZLIB_IN_USE)) + { + /* If already initialized for 'state' do not re-init. */ + if (png_ptr->zlib_state != state) + { + int ret = Z_OK; + png_const_charp who = "-"; + + /* If actually initialized for another state do a deflateEnd. */ + if (png_ptr->zlib_state != PNG_ZLIB_UNINITIALIZED) + { + ret = deflateEnd(&png_ptr->zstream); + who = "end"; + png_ptr->zlib_state = PNG_ZLIB_UNINITIALIZED; + } + + /* zlib itself detects an incomplete state on deflateEnd */ + if (ret == Z_OK) switch (state) + { +# ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED + case PNG_ZLIB_FOR_TEXT: + ret = deflateInit2(&png_ptr->zstream, + png_ptr->zlib_text_level, png_ptr->zlib_text_method, + png_ptr->zlib_text_window_bits, + png_ptr->zlib_text_mem_level, png_ptr->zlib_text_strategy); + who = "text"; + break; +# endif + + case PNG_ZLIB_FOR_IDAT: + ret = deflateInit2(&png_ptr->zstream, png_ptr->zlib_level, + png_ptr->zlib_method, png_ptr->zlib_window_bits, + png_ptr->zlib_mem_level, png_ptr->zlib_strategy); + who = "IDAT"; + break; + + default: + png_error(png_ptr, "invalid zlib state"); + } + + if (ret == Z_OK) + png_ptr->zlib_state = state; + + else /* an error in deflateEnd or deflateInit2 */ + { + size_t pos = 0; + char msg[64]; + + pos = png_safecat(msg, sizeof msg, pos, + "zlib failed to initialize compressor ("); + pos = png_safecat(msg, sizeof msg, pos, who); + + switch (ret) + { + case Z_VERSION_ERROR: + pos = png_safecat(msg, sizeof msg, pos, ") version error"); + break; + + case Z_STREAM_ERROR: + pos = png_safecat(msg, sizeof msg, pos, ") stream error"); + break; + + case Z_MEM_ERROR: + pos = png_safecat(msg, sizeof msg, pos, ") memory error"); + break; + + default: + pos = png_safecat(msg, sizeof msg, pos, ") unknown error"); + break; + } + + png_error(png_ptr, msg); + } + } + + /* Here on success, claim the zstream: */ + png_ptr->zlib_state |= PNG_ZLIB_IN_USE; + } + + else + png_error(png_ptr, "zstream already in use (internal error)"); +} + +/* The opposite: release the stream. It is also reset, this API will warn on + * error but will not fail. + */ +static void +png_zlib_release(png_structp png_ptr) +{ + if (png_ptr->zlib_state & PNG_ZLIB_IN_USE) + { + int ret = deflateReset(&png_ptr->zstream); + + png_ptr->zlib_state &= ~PNG_ZLIB_IN_USE; + + if (ret != Z_OK) + { + png_const_charp err; + PNG_WARNING_PARAMETERS(p) + + switch (ret) + { + case Z_VERSION_ERROR: + err = "version"; + break; + + case Z_STREAM_ERROR: + err = "stream"; + break; + + case Z_MEM_ERROR: + err = "memory"; + break; + + default: + err = "unknown"; + break; + } + + png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_d, ret); + png_warning_parameter(p, 2, err); + + if (png_ptr->zstream.msg) + err = png_ptr->zstream.msg; + else + err = "[no zlib message]"; + + png_warning_parameter(p, 3, err); + + png_formatted_warning(png_ptr, p, + "zlib failed to reset compressor: @1(@2): @3"); + } + } + + else + png_warning(png_ptr, "zstream not in use (internal error)"); +} + +#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED /* This pair of functions encapsulates the operation of (a) compressing a * text string, and (b) issuing it later as a series of chunk data writes. * The compression_state structure is shared context for these functions @@ -220,25 +362,22 @@ png_text_compress(png_structp png_ptr, comp->max_output_ptr = 0; comp->output_ptr = NULL; comp->input = NULL; - comp->input_len = 0; + comp->input_len = text_len; /* We may just want to pass the text right through */ if (compression == PNG_TEXT_COMPRESSION_NONE) { comp->input = (png_const_bytep)text; - comp->input_len = text_len; return((int)text_len); } if (compression >= PNG_TEXT_COMPRESSION_LAST) { -#ifdef PNG_CONSOLE_IO_SUPPORTED - char msg[50]; - png_snprintf(msg, 50, "Unknown compression type %d", compression); - png_warning(png_ptr, msg); -#else - png_warning(png_ptr, "Unknown compression type"); -#endif + PNG_WARNING_PARAMETERS(p) + + png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_d, + compression); + png_formatted_warning(png_ptr, p, "Unknown compression type @1"); } /* We can't write the chunk until we find out how much data we have, @@ -255,10 +394,12 @@ png_text_compress(png_structp png_ptr, * data, or if the input string is incredibly large (although this * wouldn't cause a failure, just a slowdown due to swapping). */ + png_zlib_claim(png_ptr, PNG_ZLIB_FOR_TEXT); /* Set up the compression buffers */ /* TODO: the following cast hides a potential overflow problem. */ png_ptr->zstream.avail_in = (uInt)text_len; + /* NOTE: assume zlib doesn't overwrite the input */ png_ptr->zstream.next_in = (Bytef *)text; png_ptr->zstream.avail_out = png_ptr->zbuf_size; @@ -418,6 +559,68 @@ png_write_compressed_data_out(png_structp png_ptr, compression_state *comp) return; } +#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED + if (comp->input_len >= 2 && comp->input_len < 16384) + { + unsigned int z_cmf; /* zlib compression method and flags */ + + /* Optimize the CMF field in the zlib stream. This hack of the zlib + * stream is compliant to the stream specification. + */ + + if (comp->num_output_ptr) + z_cmf = comp->output_ptr[0][0]; + else + z_cmf = png_ptr->zbuf[0]; + + if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70) + { + unsigned int z_cinfo; + unsigned int half_z_window_size; + png_size_t uncompressed_text_size = comp->input_len; + + z_cinfo = z_cmf >> 4; + half_z_window_size = 1 << (z_cinfo + 7); + + while (uncompressed_text_size <= half_z_window_size && + half_z_window_size >= 256) + { + z_cinfo--; + half_z_window_size >>= 1; + } + + z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4); + + if (comp->num_output_ptr) + { + + if (comp->output_ptr[0][0] != z_cmf) + { + int tmp; + + comp->output_ptr[0][0] = (png_byte)z_cmf; + tmp = comp->output_ptr[0][1] & 0xe0; + tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f; + comp->output_ptr[0][1] = (png_byte)tmp; + } + } + else + { + int tmp; + + png_ptr->zbuf[0] = (png_byte)z_cmf; + tmp = png_ptr->zbuf[1] & 0xe0; + tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f; + png_ptr->zbuf[1] = (png_byte)tmp; + } + } + + else + png_error(png_ptr, + "Invalid zlib compression method or flags in non-IDAT chunk"); + } +#endif /* PNG_WRITE_OPTIMIZE_CMF_SUPPORTED */ + /* Write saved output buffers, if any */ for (i = 0; i < comp->num_output_ptr; i++) { @@ -436,10 +639,9 @@ png_write_compressed_data_out(png_structp png_ptr, compression_state *comp) (png_size_t)(png_ptr->zbuf_size - png_ptr->zstream.avail_out)); /* Reset zlib for another zTXt/iTXt or image data */ - deflateReset(&png_ptr->zstream); - png_ptr->zstream.data_type = Z_BINARY; + png_zlib_release(png_ptr); } -#endif +#endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */ /* Write the IHDR chunk, and update the png_struct with the necessary * information. Note that the rest of this code depends upon this @@ -451,7 +653,6 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height, int interlace_type) { PNG_IHDR; - int ret; png_byte buf[13]; /* Buffer to store the IHDR info */ @@ -632,35 +833,35 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height, if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD)) png_ptr->zlib_method = 8; - ret = deflateInit2(&png_ptr->zstream, png_ptr->zlib_level, - png_ptr->zlib_method, png_ptr->zlib_window_bits, - png_ptr->zlib_mem_level, png_ptr->zlib_strategy); - - if (ret != Z_OK) - { - if (ret == Z_VERSION_ERROR) - png_error(png_ptr, - "zlib failed to initialize compressor -- version error"); - - if (ret == Z_STREAM_ERROR) - png_error(png_ptr, - "zlib failed to initialize compressor -- stream error"); +#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED +#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED + if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_STRATEGY)) + png_ptr->zlib_text_strategy = Z_DEFAULT_STRATEGY; - if (ret == Z_MEM_ERROR) - png_error(png_ptr, - "zlib failed to initialize compressor -- mem error"); + if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_LEVEL)) + png_ptr->zlib_text_level = png_ptr->zlib_level; - png_error(png_ptr, "zlib failed to initialize compressor"); - } + if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_MEM_LEVEL)) + png_ptr->zlib_text_mem_level = png_ptr->zlib_mem_level; - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - /* libpng is not interested in zstream.data_type, so set it - * to a predefined value, to avoid its evaluation inside zlib - */ - png_ptr->zstream.data_type = Z_BINARY; + if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_WINDOW_BITS)) + png_ptr->zlib_text_window_bits = png_ptr->zlib_window_bits; - png_ptr->mode = PNG_HAVE_IHDR; + if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_METHOD)) + png_ptr->zlib_text_method = png_ptr->zlib_method; +#else + png_ptr->zlib_text_strategy = Z_DEFAULT_STRATEGY; + png_ptr->zlib_text_level = png_ptr->zlib_level; + png_ptr->zlib_text_mem_level = png_ptr->zlib_mem_level; + png_ptr->zlib_text_window_bits = png_ptr->zlib_window_bits; + png_ptr->zlib_text_method = png_ptr->zlib_method; +#endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */ +#endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */ + + /* Record that the compressor has not yet been initialized. */ + png_ptr->zlib_state = PNG_ZLIB_UNINITIALIZED; + + png_ptr->mode = PNG_HAVE_IHDR; /* not READY_FOR_ZTXT */ } /* Write the palette. We are careful not to trust png_color to be in the @@ -745,12 +946,15 @@ png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length) png_debug(1, "in png_write_IDAT"); - /* Optimize the CMF field in the zlib stream. */ - /* This hack of the zlib stream is compliant to the stream specification. */ +#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED if (!(png_ptr->mode & PNG_HAVE_IDAT) && png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) { + /* Optimize the CMF field in the zlib stream. This hack of the zlib + * stream is compliant to the stream specification. + */ unsigned int z_cmf = data[0]; /* zlib compression method and flags */ + if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70) { /* Avoid memory underflows and multiplication overflows. @@ -761,11 +965,29 @@ png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length) if (length >= 2 && png_ptr->height < 16384 && png_ptr->width < 16384) { + /* Compute the maximum possible length of the datastream */ + + /* Number of pixels, plus for each row a filter byte + * and possibly a padding byte, so increase the maximum + * size to account for these. + */ + unsigned int z_cinfo; + unsigned int half_z_window_size; png_uint_32 uncompressed_idat_size = png_ptr->height * ((png_ptr->width * png_ptr->channels * png_ptr->bit_depth + 15) >> 3); - unsigned int z_cinfo = z_cmf >> 4; - unsigned int half_z_window_size = 1 << (z_cinfo + 7); + + /* If it's interlaced, each block of 8 rows is sent as up to + * 14 rows, i.e., 6 additional rows, each with a filter byte + * and possibly a padding byte + */ + if (png_ptr->interlaced) + uncompressed_idat_size += ((png_ptr->height + 7)/8) * + (png_ptr->bit_depth < 8 ? 12 : 6); + + z_cinfo = z_cmf >> 4; + half_z_window_size = 1 << (z_cinfo + 7); + while (uncompressed_idat_size <= half_z_window_size && half_z_window_size >= 256) { @@ -790,9 +1012,17 @@ png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length) png_error(png_ptr, "Invalid zlib compression method or flags in IDAT"); } +#endif /* PNG_WRITE_OPTIMIZE_CMF_SUPPORTED */ png_write_chunk(png_ptr, png_IDAT, data, length); png_ptr->mode |= PNG_HAVE_IDAT; + + /* Prior to 1.5.4 this code was replicated in every caller (except at the + * end, where it isn't technically necessary). Since this function has + * flushed the data we can safely reset the zlib output buffer here. + */ + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; } /* Write an IEND chunk */ @@ -918,7 +1148,10 @@ png_write_iCCP(png_structp png_ptr, png_const_charp name, int compression_type, (png_size_t)(name_len + 2)); if (profile_len) + { + comp.input_len = profile_len; png_write_compressed_data_out(png_ptr, &comp); + } png_write_chunk_end(png_ptr); png_free(png_ptr, new_name); @@ -1313,15 +1546,11 @@ png_check_keyword(png_structp png_ptr, png_const_charp key, png_charpp new_key) if ((png_byte)*ikp < 0x20 || ((png_byte)*ikp > 0x7E && (png_byte)*ikp < 0xA1)) { -#ifdef PNG_CONSOLE_IO_SUPPORTED - char msg[40]; + PNG_WARNING_PARAMETERS(p) - png_snprintf(msg, 40, - "invalid keyword character 0x%02X", (png_byte)*ikp); - png_warning(png_ptr, msg); -#else - png_warning(png_ptr, "invalid character in keyword"); -#endif + png_warning_parameter_unsigned(p, 1, PNG_NUMBER_FORMAT_02x, + (png_byte)*ikp); + png_formatted_warning(png_ptr, p, "invalid keyword character 0x@1"); *dp = ' '; } @@ -1499,6 +1728,7 @@ png_write_zTXt(png_structp png_ptr, png_const_charp key, png_const_charp text, png_write_chunk_data(png_ptr, &buf, (png_size_t)1); /* Write the compressed data */ + comp.input_len = text_len; png_write_compressed_data_out(png_ptr, &comp); /* Close the chunk */ @@ -1871,6 +2101,7 @@ png_write_start_row(png_structp png_ptr) png_ptr->usr_width = png_ptr->width; } + png_zlib_claim(png_ptr, PNG_ZLIB_FOR_IDAT); png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; png_ptr->zstream.next_out = png_ptr->zbuf; } @@ -1992,7 +2223,7 @@ png_write_finish_row(png_structp png_ptr) png_ptr->zstream.avail_out); } - deflateReset(&png_ptr->zstream); + png_zlib_release(png_ptr); png_ptr->zstream.data_type = Z_BINARY; } @@ -2181,6 +2412,8 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) * been specified by the application, and then writes the row out with the * chosen filter. */ +static void png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row); + #define PNG_MAXSUM (((png_uint_32)(-1)) >> 1) #define PNG_HISHIFT 10 #define PNG_LOMASK ((png_uint_32)0xffffL) @@ -2856,7 +3089,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info) /* Do the actual writing of a previously filtered row. */ -void /* PRIVATE */ +static void png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row) { png_size_t avail; @@ -2916,8 +3149,6 @@ png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row) { /* Write the IDAT and reset the zlib output buffer */ png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; } /* Repeat until all data has been compressed */ } while (avail > 0 || png_ptr->zstream.avail_in > 0); diff --git a/src/corelib/codecs/qtextcodec.cpp b/src/corelib/codecs/qtextcodec.cpp index 985f515..dd06a2a 100644 --- a/src/corelib/codecs/qtextcodec.cpp +++ b/src/corelib/codecs/qtextcodec.cpp @@ -213,12 +213,13 @@ QTextCodecCleanup::~QTextCodecCleanup() destroying_is_ok = true; #endif - for (QList<QTextCodec *>::const_iterator it = all->constBegin() - ; it != all->constEnd(); ++it) { + QList<QTextCodec *> *myAll = all; + all = 0; // Otherwise the d'tor destroys the iterator + for (QList<QTextCodec *>::const_iterator it = myAll->constBegin() + ; it != myAll->constEnd(); ++it) { delete *it; } - delete all; - all = 0; + delete myAll; localeMapper = 0; #ifdef Q_DEBUG_TEXTCODEC diff --git a/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h b/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h index 731d956..412d33c 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h @@ -77,7 +77,7 @@ public: yoff(0) { #ifdef Q_OS_SYMBIAN - if (QSysInfo::symbianVersion() == QSysInfo::SV_SF_1 || QSysInfo::symbianVersion() == QSysInfo::SV_SF_3) { + if (QSysInfo::symbianVersion() >= QSysInfo::SV_SF_1) { showInputPanelOnFocus = false; } #endif diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h index 4712c65..0325016 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h @@ -80,7 +80,7 @@ public: selectPressed(false) { #ifdef Q_OS_SYMBIAN - if (QSysInfo::symbianVersion() == QSysInfo::SV_SF_1 || QSysInfo::symbianVersion() == QSysInfo::SV_SF_3) { + if (QSysInfo::symbianVersion() >= QSysInfo::SV_SF_1) { showInputPanelOnFocus = false; } #endif diff --git a/src/gui/accessible/qaccessible_win.cpp b/src/gui/accessible/qaccessible_win.cpp index 79ac442..caabae5 100644 --- a/src/gui/accessible/qaccessible_win.cpp +++ b/src/gui/accessible/qaccessible_win.cpp @@ -600,6 +600,35 @@ HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Skip(unsigned long celt) return S_OK; } +struct AccessibleElement { + AccessibleElement(int entryId, QAccessibleInterface *accessible) { + if (entryId < 0) { + QPair<QObject*, int> ref = qAccessibleRecentSentEvents()->value(entryId); + iface = QAccessible::queryAccessibleInterface(ref.first); + entry = ref.second; + cleanupInterface = true; + } else { + iface = accessible; + entry = entryId; + cleanupInterface = false; + } + } + + QString text(QAccessible::Text t) const { + return iface ? iface->text(t, entry) : QString(); + } + + ~AccessibleElement() { + if (cleanupInterface) + delete iface; + } + + QAccessibleInterface *iface; + int entry; +private: + bool cleanupInterface; +}; + /* */ class QWindowsAccessible : public IAccessible, IOleWindow, QAccessible @@ -998,7 +1027,8 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accLocation(long *pxLeft, long *py if (!accessible->isValid()) return E_FAIL; - QRect rect = accessible->rect(varID.lVal); + AccessibleElement elem(varID.lVal, accessible); + QRect rect = elem.iface ? elem.iface->rect(elem.entry) : QRect(); if (rect.isValid()) { *pxLeft = rect.x(); *pyTop = rect.y(); @@ -1101,25 +1131,12 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChild(VARIANT varChildID, I int childIndex = varChildID.lVal; QAccessibleInterface *acc = 0; - if (childIndex < 0) { - const int entry = childIndex; - QPair<QObject*, int> ref = qAccessibleRecentSentEvents()->value(entry); - if (ref.first) { - acc = queryAccessibleInterface(ref.first); - if (acc && ref.second) { - if (ref.second) { - QAccessibleInterface *res; - int index = acc->navigate(Child, ref.second, &res); - delete acc; - if (index == -1) - return E_INVALIDARG; - acc = res; - } - } - } - } else { - RelationFlag rel = childIndex ? Child : Self; - accessible->navigate(rel, childIndex, &acc); + AccessibleElement elem(childIndex, accessible); + if (elem.iface) { + RelationFlag rel = elem.entry ? Child : Self; + int index = elem.iface->navigate(rel, elem.entry, &acc); + if (index == -1) + return E_INVALIDARG; } if (acc) { @@ -1171,7 +1188,9 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accDoDefaultAction(VARIANT varID) if (!accessible->isValid()) return E_FAIL; - return accessible->doAction(DefaultAction, varID.lVal, QVariantList()) ? S_OK : S_FALSE; + AccessibleElement elem(varID.lVal, accessible); + const bool res = elem.iface ? elem.iface->doAction(DefaultAction, elem.entry, QVariantList()) : false; + return res ? S_OK : S_FALSE; } HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accDefaultAction(VARIANT varID, BSTR* pszDefaultAction) @@ -1180,7 +1199,8 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accDefaultAction(VARIANT varID if (!accessible->isValid()) return E_FAIL; - QString def = accessible->actionText(DefaultAction, Name, varID.lVal); + AccessibleElement elem(varID.lVal, accessible); + QString def = elem.iface ? elem.iface->actionText(DefaultAction, Name, elem.entry) : QString(); if (def.isEmpty()) { *pszDefaultAction = 0; return S_FALSE; @@ -1196,7 +1216,8 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accDescription(VARIANT varID, if (!accessible->isValid()) return E_FAIL; - QString descr = accessible->text(Description, varID.lVal); + AccessibleElement elem(varID.lVal, accessible); + QString descr = elem.text(Description); if (descr.size()) { *pszDescription = QStringToBSTR(descr); return S_OK; @@ -1212,7 +1233,8 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accHelp(VARIANT varID, BSTR *p if (!accessible->isValid()) return E_FAIL; - QString help = accessible->text(Help, varID.lVal); + AccessibleElement elem(varID.lVal, accessible); + QString help = elem.text(Help); if (help.size()) { *pszHelp = QStringToBSTR(help); return S_OK; @@ -1233,7 +1255,8 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accKeyboardShortcut(VARIANT va if (!accessible->isValid()) return E_FAIL; - QString sc = accessible->text(Accelerator, varID.lVal); + AccessibleElement elem(varID.lVal, accessible); + QString sc = elem.text(Accelerator); if (sc.size()) { *pszKeyboardShortcut = QStringToBSTR(sc); return S_OK; @@ -1249,7 +1272,8 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accName(VARIANT varID, BSTR* p if (!accessible->isValid()) return E_FAIL; - QString n = accessible->text(Name, varID.lVal); + AccessibleElement elem(varID.lVal, accessible); + QString n = elem.text(Name); if (n.size()) { *pszName = QStringToBSTR(n); return S_OK; @@ -1271,7 +1295,8 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accRole(VARIANT varID, VARIANT if (!accessible->isValid()) return E_FAIL; - Role role = accessible->role(varID.lVal); + AccessibleElement elem(varID.lVal, accessible); + Role role = elem.iface ? elem.iface->role(elem.entry) : NoRole; if (role != NoRole) { if (role == LayeredPane) role = QAccessible::Pane; @@ -1290,7 +1315,8 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accState(VARIANT varID, VARIAN return E_FAIL; (*pvarState).vt = VT_I4; - (*pvarState).lVal = accessible->state(varID.lVal); + AccessibleElement elem(varID.lVal, accessible); + (*pvarState).lVal = elem.iface ? elem.iface->state(elem.entry) : 0; return S_OK; } @@ -1300,7 +1326,8 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accValue(VARIANT varID, BSTR* if (!accessible->isValid()) return E_FAIL; - QString value = accessible->text(Value, varID.lVal); + AccessibleElement elem(varID.lVal, accessible); + QString value = elem.text(Value); if (!value.isNull()) { *pszValue = QStringToBSTR(value); return S_OK; @@ -1324,19 +1351,23 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accSelect(long flagsSelect, VARIAN bool res = false; - if (flagsSelect & SELFLAG_TAKEFOCUS) - res = accessible->doAction(SetFocus, varID.lVal, QVariantList()); - if (flagsSelect & SELFLAG_TAKESELECTION) { - accessible->doAction(ClearSelection, 0, QVariantList()); - res = accessible->doAction(AddToSelection, varID.lVal, QVariantList()); + AccessibleElement elem(varID.lVal, accessible); + QAccessibleInterface *acc = elem.iface; + if (acc) { + const int entry = elem.entry; + if (flagsSelect & SELFLAG_TAKEFOCUS) + res = acc->doAction(SetFocus, entry, QVariantList()); + if (flagsSelect & SELFLAG_TAKESELECTION) { + acc->doAction(ClearSelection, 0, QVariantList()); //### bug, 0 should be entry?? + res = acc->doAction(AddToSelection, entry, QVariantList()); + } + if (flagsSelect & SELFLAG_EXTENDSELECTION) + res = acc->doAction(ExtendSelection, entry, QVariantList()); + if (flagsSelect & SELFLAG_ADDSELECTION) + res = acc->doAction(AddToSelection, entry, QVariantList()); + if (flagsSelect & SELFLAG_REMOVESELECTION) + res = acc->doAction(RemoveSelection, entry, QVariantList()); } - if (flagsSelect & SELFLAG_EXTENDSELECTION) - res = accessible->doAction(ExtendSelection, varID.lVal, QVariantList()); - if (flagsSelect & SELFLAG_ADDSELECTION) - res = accessible->doAction(AddToSelection, varID.lVal, QVariantList()); - if (flagsSelect & SELFLAG_REMOVESELECTION) - res = accessible->doAction(RemoveSelection, varID.lVal, QVariantList()); - return res ? S_OK : S_FALSE; } diff --git a/src/gui/dialogs/qfiledialog_symbian.cpp b/src/gui/dialogs/qfiledialog_symbian.cpp index cd020f6..1ffbf1d 100644 --- a/src/gui/dialogs/qfiledialog_symbian.cpp +++ b/src/gui/dialogs/qfiledialog_symbian.cpp @@ -44,7 +44,7 @@ #ifndef QT_NO_FILEDIALOG #include <private/qfiledialog_p.h> -#if defined(Q_WS_S60) && !defined(SYMBIAN_VERSION_9_4) +#if defined(Q_WS_S60) && !defined(SYMBIAN_VERSION_9_4) && !defined(SYMBIAN_VERSION_9_3) && !defined(SYMBIAN_VERSION_9_2) #include <driveinfo.h> #include <AknCommonDialogsDynMem.h> #include <CAknMemorySelectionDialogMultiDrive.h> @@ -58,7 +58,7 @@ extern QStringList qt_make_filter_list(const QString &filter); // defined in qfi extern QStringList qt_clean_filter_list(const QString &filter); // defined in qfiledialog.cpp enum DialogMode { DialogOpen, DialogSave, DialogFolder }; -#if defined(Q_WS_S60) && !defined(SYMBIAN_VERSION_9_4) +#if defined(Q_WS_S60) && !defined(SYMBIAN_VERSION_9_4) && !defined(SYMBIAN_VERSION_9_3) && !defined(SYMBIAN_VERSION_9_2) class CExtensionFilter : public CBase, public MAknFileFilter { public: @@ -104,7 +104,7 @@ static QString launchSymbianDialog(const QString dialogCaption, const QString st const QString filter, DialogMode dialogMode) { QString selection; -#if defined(Q_WS_S60) && !defined(SYMBIAN_VERSION_9_4) +#if defined(Q_WS_S60) && !defined(SYMBIAN_VERSION_9_4) && !defined(SYMBIAN_VERSION_9_3) && !defined(SYMBIAN_VERSION_9_2) TFileName startFolder; if (!startDirectory.isEmpty()) { QString dir = QDir::toNativeSeparators(QFileDialogPrivate::workingDirectory(startDirectory)); diff --git a/src/gui/egl/qegl.cpp b/src/gui/egl/qegl.cpp index 2f2f772..2a37d45 100644 --- a/src/gui/egl/qegl.cpp +++ b/src/gui/egl/qegl.cpp @@ -94,6 +94,7 @@ QEglContext::QEglContext() , current(false) , ownsContext(true) , sharing(false) + , apiChanged(false) { QEglContextTracker::ref(); } @@ -435,9 +436,20 @@ bool QEglContext::makeCurrent(EGLSurface surface) return false; } +#ifdef Q_OS_SYMBIAN + apiChanged = false; + if (currentContext(apiType) + && currentContext(apiType)->ctx != eglGetCurrentContext()) { + // some other EGL based API active. Complete its rendering + eglWaitClient(); + apiChanged = true; + } +#endif + // If lazyDoneCurrent() was called on the surface, then we may be able // to assume that it is still current within the thread. - if (surface == currentSurface && currentContext(apiType) == this) { + if (surface == currentSurface && currentContext(apiType) == this + && !apiChanged) { current = true; return true; } @@ -512,6 +524,13 @@ bool QEglContext::swapBuffers(EGLSurface surface) bool ok = eglSwapBuffers(QEgl::display(), surface); if (!ok) qWarning() << "QEglContext::swapBuffers():" << QEgl::errorString(); + +#ifdef Q_OS_SYMBIAN + if (apiChanged) { + eglWaitClient(); + apiChanged = false; + } +#endif return ok; } diff --git a/src/gui/egl/qeglcontext_p.h b/src/gui/egl/qeglcontext_p.h index 6cd76b3..0cdaae7 100644 --- a/src/gui/egl/qeglcontext_p.h +++ b/src/gui/egl/qeglcontext_p.h @@ -104,6 +104,7 @@ private: bool current; bool ownsContext; bool sharing; + bool apiChanged; static QEglContext *currentContext(QEgl::API api); static void setCurrentContext(QEgl::API api, QEglContext *context); diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp index 5ddd53f..33daa99 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp +++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp @@ -252,9 +252,6 @@ bool QCoeFepInputContext::needsInputPanel() bool QCoeFepInputContext::filterEvent(const QEvent *event) { - // The CloseSoftwareInputPanel event is not handled here, because the VK will automatically - // close when it discovers that the underlying widget does not have input capabilities. - if (!focusWidget()) return false; @@ -318,6 +315,11 @@ bool QCoeFepInputContext::filterEvent(const QEvent *event) if (!needsInputPanel()) return false; + if (event->type() == QEvent::CloseSoftwareInputPanel) { + m_fepState->ReportAknEdStateEventL(MAknEdStateObserver::EAknClosePenInputRequest); + return false; + } + if (event->type() == QEvent::RequestSoftwareInputPanel) { // Only request virtual keyboard if it is not yet active or if this is the first time // panel is requested for this application. @@ -474,7 +476,7 @@ void QCoeFepInputContext::resetSplitViewWidget(bool keepInputWidget) if (!alwaysResize) { if (gv->scene()) { - if (gv->scene()->focusItem()) { + if (gv->scene()->focusItem() && S60->partial_keyboardAutoTranslation) { // Check if the widget contains cursorPositionChanged signal and disconnect from it. QByteArray signal = QMetaObject::normalizedSignature(SIGNAL(cursorPositionChanged())); int index = gv->scene()->focusItem()->toGraphicsObject()->metaObject()->indexOfSignal(signal.right(signal.length() - 1)); @@ -580,7 +582,7 @@ void QCoeFepInputContext::ensureFocusWidgetVisible(QWidget *widget) if (!moveWithinVisibleArea) { // Check if the widget contains cursorPositionChanged signal and connect to it. QByteArray signal = QMetaObject::normalizedSignature(SIGNAL(cursorPositionChanged())); - if (gv->scene() && gv->scene()->focusItem()) { + if (gv->scene() && gv->scene()->focusItem() && S60->partial_keyboardAutoTranslation) { int index = gv->scene()->focusItem()->toGraphicsObject()->metaObject()->indexOfSignal(signal.right(signal.length() - 1)); if (index != -1) connect(gv->scene()->focusItem()->toGraphicsObject(), SIGNAL(cursorPositionChanged()), this, SLOT(translateInputWidget())); diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index e32fdeb..0fbae59 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -66,9 +66,14 @@ #include <qdebug.h> @interface NSEvent (Qt_Compile_Leopard_DeviceDelta) + // SnowLeopard: - (CGFloat)deviceDeltaX; - (CGFloat)deviceDeltaY; - (CGFloat)deviceDeltaZ; + // Lion: + - (CGFloat)scrollingDeltaX; + - (CGFloat)scrollingDeltaY; + - (CGFloat)scrollingDeltaZ; @end @interface NSEvent (Qt_Compile_Leopard_Gestures) @@ -614,7 +619,6 @@ static int qCocoaViewCount = 0; int deltaX = 0; int deltaY = 0; - int deltaZ = 0; const EventRef carbonEvent = (EventRef)[theEvent eventRef]; const UInt32 carbonEventKind = carbonEvent ? ::GetEventKind(carbonEvent) : 0; @@ -627,15 +631,20 @@ static int qCocoaViewCount = 0; // It looks like 1/4 degrees per pixel behaves most native. // (NB: Qt expects the unit for delta to be 8 per degree): const int pixelsToDegrees = 2; // 8 * 1/4 - deltaX = [theEvent deviceDeltaX] * pixelsToDegrees; - deltaY = [theEvent deviceDeltaY] * pixelsToDegrees; - deltaZ = [theEvent deviceDeltaZ] * pixelsToDegrees; + if (QSysInfo::MacintoshVersion <= QSysInfo::MV_10_6) { + // Mac OS 10.6 + deltaX = [theEvent deviceDeltaX] * pixelsToDegrees; + deltaY = [theEvent deviceDeltaY] * pixelsToDegrees; + } else { + // Mac OS 10.7+ + deltaX = [theEvent scrollingDeltaX] * pixelsToDegrees; + deltaY = [theEvent scrollingDeltaY] * pixelsToDegrees; + } } else { // carbonEventKind == kEventMouseWheelMoved // Remove acceleration, and use either -120 or 120 as delta: deltaX = qBound(-120, int([theEvent deltaX] * 10000), 120); deltaY = qBound(-120, int([theEvent deltaY] * 10000), 120); - deltaZ = qBound(-120, int([theEvent deltaZ] * 10000), 120); } #ifndef QT_NO_WHEELEVENT @@ -654,13 +663,6 @@ static int qCocoaViewCount = 0; qt_sendSpontaneousEvent(widgetToGetMouse, &qwe); } - if (deltaZ != 0) { - // Qt doesn't explicitly support wheels with a Z component. In a misguided attempt to - // try to be ahead of the pack, I'm adding this extra value. - QWheelEvent qwe(qlocal, qglobal, deltaZ, buttons, keyMods, (Qt::Orientation)3); - qt_sendSpontaneousEvent(widgetToGetMouse, &qwe); - } - if (deltaX != 0 && deltaY != 0) QMacScrollOptimization::performDelayedScroll(); #endif //QT_NO_WHEELEVENT diff --git a/src/gui/kernel/qcursor_win.cpp b/src/gui/kernel/qcursor_win.cpp index 9f0c516..cef83f5 100644 --- a/src/gui/kernel/qcursor_win.cpp +++ b/src/gui/kernel/qcursor_win.cpp @@ -477,6 +477,7 @@ void QCursorData::update() QPixmap pixmap = QApplicationPrivate::instance()->getPixmapCursor(cshape); hcurs = create32BitCursor(pixmap, hx, hy); } + break; default: qWarning("QCursor::update: Invalid cursor shape %d", cshape); return; diff --git a/src/gui/kernel/qsoftkeymanager.cpp b/src/gui/kernel/qsoftkeymanager.cpp index 500bcff..9caa37e 100644 --- a/src/gui/kernel/qsoftkeymanager.cpp +++ b/src/gui/kernel/qsoftkeymanager.cpp @@ -102,7 +102,7 @@ QSoftKeyManager::QSoftKeyManager() : QAction *QSoftKeyManager::createAction(StandardSoftKey standardKey, QWidget *actionWidget) { QAction *action = new QAction(standardSoftKeyText(standardKey), actionWidget); -#if defined(Q_WS_S60) && !defined(SYMBIAN_VERSION_9_4) +#if defined(Q_WS_S60) && !defined(SYMBIAN_VERSION_9_4) && !defined(SYMBIAN_VERSION_9_3) && !defined(SYMBIAN_VERSION_9_2) int key = 0; switch (standardKey) { case OkSoftKey: @@ -123,8 +123,10 @@ QAction *QSoftKeyManager::createAction(StandardSoftKey standardKey, QWidget *act default: break; }; - if (key != 0) + if (key != 0) { QSoftKeyManager::instance()->d_func()->softKeyCommandActions.insert(action, key); + connect(action, SIGNAL(destroyed(QObject*)), QSoftKeyManager::instance(), SLOT(cleanupHash(QObject*))); + } #endif QAction::SoftKeyRole softKeyRole = QAction::NoSoftKey; switch (standardKey) { @@ -157,7 +159,13 @@ QAction *QSoftKeyManager::createKeyedAction(StandardSoftKey standardKey, Qt::Key QScopedPointer<QAction> action(createAction(standardKey, actionWidget)); connect(action.data(), SIGNAL(triggered()), QSoftKeyManager::instance(), SLOT(sendKeyEvent())); + +#if defined(Q_WS_S60) && !defined(SYMBIAN_VERSION_9_4) && !defined(SYMBIAN_VERSION_9_3) && !defined(SYMBIAN_VERSION_9_2) + // Don't connect destroyed slot if is was already connected in createAction + if (!(QSoftKeyManager::instance()->d_func()->softKeyCommandActions.contains(action.data()))) +#endif connect(action.data(), SIGNAL(destroyed(QObject*)), QSoftKeyManager::instance(), SLOT(cleanupHash(QObject*))); + QSoftKeyManager::instance()->d_func()->keyedActions.insert(action.data(), key); return action.take(); #endif //QT_NO_ACTION @@ -166,9 +174,11 @@ QAction *QSoftKeyManager::createKeyedAction(StandardSoftKey standardKey, Qt::Key void QSoftKeyManager::cleanupHash(QObject *obj) { Q_D(QSoftKeyManager); - QAction *action = qobject_cast<QAction*>(obj); + // Can't use qobject_cast in destroyed() signal handler as that'll return NULL, + // so use static_cast instead. Since the pointer is only used as a hash key, it is safe. + QAction *action = static_cast<QAction *>(obj); d->keyedActions.remove(action); -#if defined(Q_WS_S60) && !defined(SYMBIAN_VERSION_9_4) +#if defined(Q_WS_S60) && !defined(SYMBIAN_VERSION_9_4) && !defined(SYMBIAN_VERSION_9_3) && !defined(SYMBIAN_VERSION_9_2) d->softKeyCommandActions.remove(action); #endif } diff --git a/src/gui/kernel/qsoftkeymanager_common_p.h b/src/gui/kernel/qsoftkeymanager_common_p.h index e9cbd7d..9a11eec 100644 --- a/src/gui/kernel/qsoftkeymanager_common_p.h +++ b/src/gui/kernel/qsoftkeymanager_common_p.h @@ -72,7 +72,7 @@ protected: QMultiHash<int, QAction*> requestedSoftKeyActions; QWidget *initialSoftKeySource; bool pendingUpdate; -#if defined(Q_WS_S60) && !defined(SYMBIAN_VERSION_9_4) +#if defined(Q_WS_S60) && !defined(SYMBIAN_VERSION_9_4) && !defined(SYMBIAN_VERSION_9_3) && !defined(SYMBIAN_VERSION_9_2) QHash<QAction*, int> softKeyCommandActions; #endif }; diff --git a/src/gui/kernel/qsoftkeymanager_s60.cpp b/src/gui/kernel/qsoftkeymanager_s60.cpp index b5d0101..999fccc 100644 --- a/src/gui/kernel/qsoftkeymanager_s60.cpp +++ b/src/gui/kernel/qsoftkeymanager_s60.cpp @@ -117,7 +117,7 @@ void QSoftKeyManagerPrivateS60::ensureCbaVisibilityAndResponsiviness(CEikButtonG void QSoftKeyManagerPrivateS60::clearSoftkeys(CEikButtonGroupContainer &cba) { -#if defined(Q_WS_S60) && !defined(SYMBIAN_VERSION_9_4) +#if defined(Q_WS_S60) && !defined(SYMBIAN_VERSION_9_4) && !defined(SYMBIAN_VERSION_9_3) && !defined(SYMBIAN_VERSION_9_2) QT_TRAP_THROWING( //EAknSoftkeyEmpty is used, because using -1 adds softkeys without actions on Symbian3 cba.SetCommandL(0, EAknSoftkeyEmpty, KNullDesC); @@ -317,7 +317,7 @@ bool QSoftKeyManagerPrivateS60::setSoftkey(CEikButtonGroupContainer &cba, QString text = softkeyText(*action); TPtrC nativeText = qt_QString2TPtrC(text); int command = S60_COMMAND_START + position; -#if defined(Q_WS_S60) && !defined(SYMBIAN_VERSION_9_4) +#if defined(Q_WS_S60) && !defined(SYMBIAN_VERSION_9_4) && !defined(SYMBIAN_VERSION_9_3) && !defined(SYMBIAN_VERSION_9_2) if (softKeyCommandActions.contains(action)) command = softKeyCommandActions.value(action); #endif diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h index c429b04..3ec4052 100644 --- a/src/gui/kernel/qt_s60_p.h +++ b/src/gui/kernel/qt_s60_p.h @@ -77,8 +77,8 @@ #include <akncontext.h> // CAknContextPane #include <eikspane.h> // CEikStatusPane #include <AknPopupFader.h> // MAknFadedComponent and TAknPopupFader -#include <gfxtranseffect/gfxtranseffect.h> // BeginFullScreen #ifdef QT_SYMBIAN_HAVE_AKNTRANSEFFECT_H +#include <gfxtranseffect/gfxtranseffect.h> // BeginFullScreen #include <akntranseffect.h> // BeginFullScreen #endif #endif diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index d6aaa3f..807f68e 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -238,7 +238,7 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) bool checkExtra = true; if (q->isWindow() && (data.window_state & (Qt::WindowFullScreen | Qt::WindowMaximized))) { // Do not allow fullscreen/maximized windows to expand beyond client rect - TRect r = static_cast<CEikAppUi*>(S60->appUi())->ClientRect(); + TRect r = S60->clientRect(); w = qMin(w, r.Width()); h = qMin(h, r.Height()); diff --git a/src/gui/styles/qmacstyle_mac.mm b/src/gui/styles/qmacstyle_mac.mm index 8436856..1c1713c 100644 --- a/src/gui/styles/qmacstyle_mac.mm +++ b/src/gui/styles/qmacstyle_mac.mm @@ -1063,7 +1063,7 @@ bool qt_mac_buttonIsRenderedFlat(const QPushButton *pushButton, const QStyleOpti { QMacStyle *macStyle = qobject_cast<QMacStyle *>(pushButton->style()); if (!macStyle) - return false; + return true; // revert to 'flat' behavior if not Mac style HIThemeButtonDrawInfo bdi; macStyle->d->initHIThemePushButton(option, pushButton, kThemeStateActive, &bdi); return bdi.kind == kThemeBevelButton; diff --git a/src/gui/text/qfontdatabase_s60.cpp b/src/gui/text/qfontdatabase_s60.cpp index cf96733..ffa4e59 100644 --- a/src/gui/text/qfontdatabase_s60.cpp +++ b/src/gui/text/qfontdatabase_s60.cpp @@ -58,7 +58,7 @@ #endif // SYMBIAN_ENABLE_SPLIT_HEADERS #endif // QT_NO_FREETYPE -#ifndef SYMBIAN_VERSION_9_4 +#if !defined(SYMBIAN_VERSION_9_4) && !defined(SYMBIAN_VERSION_9_3) && !defined(SYMBIAN_VERSION_9_2) #define SYMBIAN_LINKEDFONTS_SUPPORTED #endif // !SYMBIAN_VERSION_9_4 diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp index aacac04..e32e112 100644 --- a/src/gui/text/qtextcontrol.cpp +++ b/src/gui/text/qtextcontrol.cpp @@ -1665,8 +1665,10 @@ void QTextControlPrivate::mouseMoveEvent(QEvent *e, Qt::MouseButton button, cons #endif //QT_NO_IM } else { //emit q->visibilityRequest(QRectF(mousePos, QSizeF(1, 1))); - if (cursor.position() != oldCursorPos) + if (cursor.position() != oldCursorPos) { emit q->cursorPositionChanged(); + emit q->microFocusChanged(); + } } selectionChanged(true); repaintOldAndNewSelection(oldSelection); @@ -1710,8 +1712,10 @@ void QTextControlPrivate::mouseReleaseEvent(QEvent *e, Qt::MouseButton button, c repaintOldAndNewSelection(oldSelection); - if (cursor.position() != oldCursorPos) + if (cursor.position() != oldCursorPos) { emit q->cursorPositionChanged(); + emit q->microFocusChanged(); + } if (interactionFlags & Qt::LinksAccessibleByMouse) { if (!(button & Qt::LeftButton)) diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp index f4cb742..39d0e6c 100644 --- a/src/gui/text/qtextdocument_p.cpp +++ b/src/gui/text/qtextdocument_p.cpp @@ -540,6 +540,7 @@ int QTextDocumentPrivate::remove_block(int pos, int *blockFormat, int command, Q int n = blocks.next(b); Q_ASSERT((int)blocks.position(n) == pos + 1); blocks.setSize(b, blocks.size(b) + blocks.size(n) - 1); + blocks.fragment(b)->userState = blocks.fragment(n)->userState; b = n; } *blockFormat = blocks.fragment(b)->format; diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 093b43d..9301f16 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1532,33 +1532,40 @@ void QTextEngine::itemize() const const ushort *e = uc + length; int lastScript = QUnicodeTables::Common; while (uc < e) { - int script = QUnicodeTables::script(*uc); - if (script == QUnicodeTables::Inherited) - script = lastScript; - analysis->flags = QScriptAnalysis::None; - if (*uc == QChar::ObjectReplacementCharacter) { + switch (*uc) { + case QChar::ObjectReplacementCharacter: if (analysis->bidiLevel % 2) --analysis->bidiLevel; analysis->script = QUnicodeTables::Common; analysis->flags = QScriptAnalysis::Object; - } else if (*uc == QChar::LineSeparator) { + break; + case QChar::LineSeparator: if (analysis->bidiLevel % 2) --analysis->bidiLevel; analysis->script = QUnicodeTables::Common; analysis->flags = QScriptAnalysis::LineOrParagraphSeparator; if (option.flags() & QTextOption::ShowLineAndParagraphSeparators) *const_cast<ushort*>(uc) = 0x21B5; // visual line separator - } else if (*uc == 9) { + break; + case 9: // Tab analysis->script = QUnicodeTables::Common; analysis->flags = QScriptAnalysis::Tab; analysis->bidiLevel = control.baseLevel(); - } else if ((*uc == 32 || *uc == QChar::Nbsp) - && (option.flags() & QTextOption::ShowTabsAndSpaces)) { - analysis->script = QUnicodeTables::Common; - analysis->flags = QScriptAnalysis::Space; - analysis->bidiLevel = control.baseLevel(); - } else { - analysis->script = script; + break; + case 32: // Space + case QChar::Nbsp: + if (option.flags() & QTextOption::ShowTabsAndSpaces) { + analysis->script = QUnicodeTables::Common; + analysis->flags = QScriptAnalysis::Space; + analysis->bidiLevel = control.baseLevel(); + break; + } + // fall through + default: + int script = QUnicodeTables::script(*uc); + analysis->script = script == QUnicodeTables::Inherited ? lastScript : script; + analysis->flags = QScriptAnalysis::None; + break; } lastScript = analysis->script; ++uc; @@ -2426,7 +2433,7 @@ void QTextEngine::indexAdditionalFormats() between the text that gets truncated and the ellipsis. This is important to get correctly shaped results for arabic text. */ -static bool nextCharJoins(const QString &string, int pos) +static inline bool nextCharJoins(const QString &string, int pos) { while (pos < string.length() && string.at(pos).category() == QChar::Mark_NonSpacing) ++pos; @@ -2435,13 +2442,14 @@ static bool nextCharJoins(const QString &string, int pos) return string.at(pos).joining() != QChar::OtherJoining; } -static bool prevCharJoins(const QString &string, int pos) +static inline bool prevCharJoins(const QString &string, int pos) { while (pos > 0 && string.at(pos - 1).category() == QChar::Mark_NonSpacing) --pos; if (pos == 0) return false; - return (string.at(pos - 1).joining() == QChar::Dual || string.at(pos - 1).joining() == QChar::Center); + QChar::Joining joining = string.at(pos - 1).joining(); + return (joining == QChar::Dual || joining == QChar::Center); } QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int flags) const diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index b6e2f90..a8031e7 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE #ifdef QT_GUI_PASSWORD_ECHO_DELAY -static int qt_passwordEchoDelay = QT_GUI_PASSWORD_ECHO_DELAY; +static const int qt_passwordEchoDelay = QT_GUI_PASSWORD_ECHO_DELAY; #endif /*! @@ -93,8 +93,8 @@ void QLineControl::updateDisplayText(bool forceUpdate) if (m_echoMode == QLineEdit::Password) { str.fill(m_passwordCharacter); #ifdef QT_GUI_PASSWORD_ECHO_DELAY - if (m_passwordEchoTimer != 0 && !str.isEmpty()) { - int cursor = m_text.length() - 1; + if (m_passwordEchoTimer != 0 && m_cursor > 0 && m_cursor <= m_text.length()) { + int cursor = m_cursor - 1; QChar uc = m_text.at(cursor); str[cursor] = uc; if (cursor > 0 && uc.unicode() >= 0xdc00 && uc.unicode() < 0xe000) { diff --git a/src/network/kernel/qauthenticator.cpp b/src/network/kernel/qauthenticator.cpp index 4f7f4ed..0423e22 100644 --- a/src/network/kernel/qauthenticator.cpp +++ b/src/network/kernel/qauthenticator.cpp @@ -395,7 +395,7 @@ void QAuthenticatorPrivate::parseHttpResponse(const QList<QPair<QByteArray, QByt case Basic: if(realm.isEmpty()) this->options[QLatin1String("realm")] = realm = QString::fromLatin1(options.value("realm")); - if (user.isEmpty()) + if (user.isEmpty() && password.isEmpty()) phase = Done; break; case Ntlm: @@ -406,7 +406,7 @@ void QAuthenticatorPrivate::parseHttpResponse(const QList<QPair<QByteArray, QByt this->options[QLatin1String("realm")] = realm = QString::fromLatin1(options.value("realm")); if (options.value("stale").toLower() == "true") phase = Start; - if (user.isEmpty()) + if (user.isEmpty() && password.isEmpty()) phase = Done; break; } diff --git a/src/s60installs/s60installs.pro b/src/s60installs/s60installs.pro index 0164141..a43c3df 100755 --- a/src/s60installs/s60installs.pro +++ b/src/s60installs/s60installs.pro @@ -10,10 +10,10 @@ symbian: { TARGET = "Qt$${QT_LIBINFIX}" isEmpty(QT_LIBINFIX) { - TARGET.UID3 = 0x2001e61c + TARGET.UID3 = 0x2001E61C } else { # Always use experimental UID for infixed configuration to avoid UID clash - TARGET.UID3 = 0xe001e61c + TARGET.UID3 = 0xE001E61C } VERSION=$${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION}.$${QT_PATCH_VERSION} @@ -103,7 +103,7 @@ symbian: { # Support backup & restore for Qt libraries qtbackup.files = backup_registration.xml - qtbackup.path = c:/private/10202d56/import/packages/$$replace(TARGET.UID3, 0x,) + qtbackup.path = c:/private/10202d56/import/packages/$$lower($$replace(TARGET.UID3, 0x,)) DEPLOYMENT += qtlibraries \ qtbackup \ diff --git a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp index 8530c7f..5d6f2a2 100644 --- a/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp +++ b/tests/auto/declarative/qdeclarativetextedit/tst_qdeclarativetextedit.cpp @@ -1679,15 +1679,26 @@ void tst_qdeclarativetextedit::cursorDelegate() QInputMethodEvent event; QApplication::sendEvent(view, &event); + // Test delegate gets moved on mouse press. textEditObject->setSelectByMouse(true); textEditObject->setCursorPosition(0); - qDebug() << textEditObject->boundingRect() << textEditObject->positionToRectangle(5).center() << view->mapFromScene(textEditObject->positionToRectangle(5).center()); - QTest::mouseClick(view->viewport(), Qt::LeftButton, 0, view->mapFromScene(textEditObject->positionToRectangle(5).center())); + const QPoint point1 = view->mapFromScene(textEditObject->positionToRectangle(5).center()); + QTest::mouseClick(view->viewport(), Qt::LeftButton, 0, point1); QVERIFY(textEditObject->cursorPosition() != 0); QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x())); QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y())); + // Test delegate gets moved on mouse drag + textEditObject->setCursorPosition(0); + const QPoint point2 = view->mapFromScene(textEditObject->positionToRectangle(10).center()); + QTest::mousePress(view->viewport(), Qt::LeftButton, 0, point1); + QMouseEvent mv(QEvent::MouseMove, point2, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier); + QApplication::sendEvent(view->viewport(), &mv); + QTest::mouseRelease(view->viewport(), Qt::LeftButton, 0, point2); + QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x())); + QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y())); + textEditObject->setReadOnly(true); textEditObject->setCursorPosition(0); QTest::mouseClick(view->viewport(), Qt::LeftButton, 0, view->mapFromScene(textEditObject->positionToRectangle(5).center())); @@ -1696,6 +1707,12 @@ void tst_qdeclarativetextedit::cursorDelegate() QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y())); textEditObject->setCursorPosition(0); + QTest::mouseClick(view->viewport(), Qt::LeftButton, 0, view->mapFromScene(textEditObject->positionToRectangle(5).center())); + QVERIFY(textEditObject->cursorPosition() != 0); + QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x())); + QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y())); + + textEditObject->setCursorPosition(0); QCOMPARE(textEditObject->cursorRectangle().x(), qRound(delegateObject->x())); QCOMPARE(textEditObject->cursorRectangle().y(), qRound(delegateObject->y())); QVERIFY(textEditObject->cursorRectangle().y() >= 0); diff --git a/tests/auto/qlineedit/tst_qlineedit.cpp b/tests/auto/qlineedit/tst_qlineedit.cpp index 6abbdcd..2c88561 100644 --- a/tests/auto/qlineedit/tst_qlineedit.cpp +++ b/tests/auto/qlineedit/tst_qlineedit.cpp @@ -1770,6 +1770,13 @@ void tst_QLineEdit::passwordEchoDelay() QApplication::sendEvent(testWidget, &ev); QCOMPARE(testWidget->displayText(), QString(7, fillChar) + QLatin1Char('7')); + testWidget->setCursorPosition(3); + QCOMPARE(testWidget->displayText(), QString(7, fillChar) + QLatin1Char('7')); + QTest::keyPress(testWidget, 'a'); + QCOMPARE(testWidget->displayText(), QString(3, fillChar) + QLatin1Char('a') + QString(5, fillChar)); + QTest::keyPress(testWidget, Qt::Key_Backspace); + QCOMPARE(testWidget->displayText(), QString(8, fillChar)); + // restore clean state testWidget->setEchoMode(QLineEdit::Normal); } diff --git a/tests/auto/qpushbutton/tst_qpushbutton.cpp b/tests/auto/qpushbutton/tst_qpushbutton.cpp index 7742f6b..db4f385 100644 --- a/tests/auto/qpushbutton/tst_qpushbutton.cpp +++ b/tests/auto/qpushbutton/tst_qpushbutton.cpp @@ -91,6 +91,9 @@ private slots: void animateClick(); void toggle(); void clicked(); +#ifdef Q_OS_MAC + void macClicked(); +#endif void toggled(); void isEnabled(); void defaultAndAutoDefault(); @@ -469,6 +472,34 @@ void tst_QPushButton::clicked() QCOMPARE( release_count, (uint)10 ); } +#ifdef Q_OS_MAC +// test that the corners of a mac style button are not treated as clicks. +// but that if a style is applied, they are. +void tst_QPushButton::macClicked() +{ + QPushButton *macTestWidget = new QPushButton( "Push button" ); + macTestWidget->show(); + connect( macTestWidget, SIGNAL(clicked()), this, SLOT(onClicked()) ); + + QTest::mouseClick( macTestWidget, Qt::LeftButton, 0, QPoint(1,1) ); + QVERIFY( click_count == 0 ); + + QTest::mouseClick( macTestWidget, Qt::LeftButton, 0, macTestWidget->rect().center() ); + QVERIFY( click_count == 1 ); + + resetCounters(); + macTestWidget->setStyleSheet("background: white;"); + + QTest::mouseClick( macTestWidget, Qt::LeftButton, 0, QPoint(1,1) ); + QVERIFY( click_count == 1 ); + + QTest::mouseClick( macTestWidget, Qt::LeftButton, 0, macTestWidget->rect().center() ); + QVERIFY( click_count == 2 ); + + delete macTestWidget; +} +#endif + /* void tst_QPushButton::group() { diff --git a/tests/auto/qtextcursor/tst_qtextcursor.cpp b/tests/auto/qtextcursor/tst_qtextcursor.cpp index 2b0ba42..cc3b1dc 100644 --- a/tests/auto/qtextcursor/tst_qtextcursor.cpp +++ b/tests/auto/qtextcursor/tst_qtextcursor.cpp @@ -50,6 +50,7 @@ #include <qabstracttextdocumentlayout.h> #include <qtextlayout.h> #include <qtextcursor.h> +#include <qtextobject.h> #include <qdebug.h> //TESTED_FILES=gui/text/qtextcursor.cpp gui/text/qtextcursor_p.h @@ -154,6 +155,8 @@ private slots: void cursorPositionWithBlockUndoAndRedo2(); void cursorPositionWithBlockUndoAndRedo3(); + void joinNonEmptyRemovedBlockUserState(); + private: int blockCount(); @@ -1858,5 +1861,20 @@ void tst_QTextCursor::cursorPositionWithBlockUndoAndRedo3() QCOMPARE(cursor.position(), cursorPositionBefore); } +void tst_QTextCursor::joinNonEmptyRemovedBlockUserState() +{ + cursor.insertText("Hello"); + cursor.insertBlock(); + cursor.insertText("World"); + cursor.block().setUserState(10); + + cursor.movePosition(QTextCursor::EndOfBlock); + cursor.movePosition(QTextCursor::PreviousBlock, QTextCursor::KeepAnchor); + cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); + cursor.removeSelectedText(); + + QCOMPARE(cursor.block().userState(), 10); +} + QTEST_MAIN(tst_QTextCursor) #include "tst_qtextcursor.moc" diff --git a/translations/qt_fa.ts b/translations/qt_fa.ts new file mode 100644 index 0000000..ec5df32 --- /dev/null +++ b/translations/qt_fa.ts @@ -0,0 +1,9800 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.0" language="fa"> +<context> + <name>CloseButton</name> + <message> + <source>Close Tab</source> + <translation>بستن برگه</translation> + </message> +</context> +<context> + <name>FakeReply</name> + <message> + <source>Fake error !</source> + <translation>خطای تقلبی!</translation> + </message> + <message> + <source>Invalid URL</source> + <translation>URL نامعتبر</translation> + </message> +</context> +<context> + <name>MAC_APPLICATION_MENU</name> + <message> + <source>Services</source> + <translation>خدمات</translation> + </message> + <message> + <source>Hide %1</source> + <translation> مخفی کردن %1</translation> + </message> + <message> + <source>Hide Others</source> + <translation>مخفی کردن بقیه</translation> + </message> + <message> + <source>Show All</source> + <translation>نمایش همه</translation> + </message> + <message> + <source>Preferences...</source> + <translation>ترجیهات...</translation> + </message> + <message> + <source>Quit %1</source> + <translation>اتمام %1</translation> + </message> + <message> + <source>About %1</source> + <translation>درباره %1</translation> + </message> +</context> +<context> + <name>Phonon::</name> + <message> + <source>Notifications</source> + <translation>اعلانات</translation> + </message> + <message> + <source>Music</source> + <translation>موسیقی</translation> + </message> + <message> + <source>Video</source> + <translation>ویدیو</translation> + </message> + <message> + <source>Communication</source> + <translation>ارتباطات</translation> + </message> + <message> + <source>Games</source> + <translation>بازیها</translation> + </message> + <message> + <source>Accessibility</source> + <translation>قابلیت دسترسی</translation> + </message> +</context> +<context> + <name>Phonon::AudioOutput</name> + <message> + <source><html>The audio playback device <b>%1</b> does not work.<br/>Falling back to <b>%2</b>.</html></source> + <translation><html>دستگاه پخش صوت <b>%1</b> کار نمیکند.<br/>بازگشت به <b>%2</b>.</html></translation> + </message> + <message> + <source><html>Switching to the audio playback device <b>%1</b><br/>which just became available and has higher preference.</html></source> + <translation><html>سوئیچ کردن به دستگاه پخش صوت <b>%1</b><br/>که تازه در دسترس قرار گرفته است و امکانات بیشتری دارد.</html></translation> + </message> + <message> + <source>Revert back to device '%1'</source> + <translation>بازگشت دوباره به دستگاه '%1'</translation> + </message> + <message> + <source><html>Switching to the audio playback device <b>%1</b><br/>which has higher preference or is specifically configured for this stream.</html></source> + <translation><html>سوئیچ کردن به دستگاه پخش صوت<b>%1</b><br/>که امکانات بیشتری دارد یا به طور مخصوص برای این نوع جریان پیکربندی شده است</html></translation> + </message> +</context> +<context> + <name>Phonon::Gstreamer::Backend</name> + <message> + <source>Warning: You do not seem to have the package gstreamer0.10-plugins-good installed. + Some video features have been disabled.</source> + <translation>هشدار: به نظر میرسد شما بستهٔ gstreamer0.10-plugins-good را نصب نکردهاید. + بعضی از ویژگیهای ویدیویی غیرفعال شده اند.</translation> + </message> + <message> + <source>Warning: You do not seem to have the base GStreamer plugins installed. + All audio and video support has been disabled</source> + <translation>هشدار: به نظر میرسد شما افزونههای پایه GStreamer را نصب نکردهاید. + تمامی پشتیبانیهای صوتی و تصویری غیرفعال شدهاند</translation> + </message> +</context> +<context> + <name>Phonon::Gstreamer::MediaObject</name> + <message> + <source>Cannot start playback. + +Check your GStreamer installation and make sure you +have libgstreamer-plugins-base installed.</source> + <translation>نمیتوان پخش را شروع کرد. + +وضعیت نصب GStreamer خود را بررسی کنید و اطمینان حاصل نمایید که libgstreamer-plugins-base را نصب کردهاید.</translation> + </message> + <message> + <source>Missing codec helper script assistant.</source> + <translation>اسکریپت کمکی کدک یافت نشد.</translation> + </message> + <message> + <source>Plugin codec installation failed for codec: %0</source> + <translation>نصب ناموفق افزونه دیکدر برای دیکد کردن: %0</translation> + </message> + <message> + <source>A required codec is missing. You need to install the following codec(s) to play this content: %0</source> + <translation>رمزگشای مورد نیاز یافت نشد. شما میبایست رمز گشای ذیل را برای اجرای این مضمون نصب کنید: %0</translation> + </message> + <message> + <source>Could not open media source.</source> + <translation>نمیتوان منبع رسانه را باز کرد.</translation> + </message> + <message> + <source>Invalid source type.</source> + <translation>نوع منبع نامعتبر.</translation> + </message> + <message> + <source>Could not locate media source.</source> + <translation>نمیتوان محل منبع رسانهای را پیدا کرد.</translation> + </message> + <message> + <source>Could not open audio device. The device is already in use.</source> + <translation>نمیتوان دستگاه صوتی را باز کرد. دستگاه هماکنون در حال استفاده است.</translation> + </message> + <message> + <source>Could not decode media source.</source> + <translation>نمیتوان منبع رسانه را رمزگشایی کرد.</translation> + </message> +</context> +<context> + <name>Phonon::MMF</name> + <message> + <source>Audio Output</source> + <translation>خروجی صدا</translation> + </message> + <message> + <source>The audio output device</source> + <translation>دستگاه خروجی صدا</translation> + </message> + <message> + <source>No error</source> + <translation>خطایی وجود ندارد</translation> + </message> + <message> + <source>Not found</source> + <translation>پیدا نشد</translation> + </message> + <message> + <source>Out of memory</source> + <translation>خارج از حافظه</translation> + </message> + <message> + <source>Not supported</source> + <translation>پشتیبانی نشده</translation> + </message> + <message> + <source>Overflow</source> + <translation>سرریز</translation> + </message> + <message> + <source>Underflow</source> + <translation>فروریز</translation> + </message> + <message> + <source>Already exists</source> + <translation>از قبل موجود است</translation> + </message> + <message> + <source>Path not found</source> + <translation>مسیر پیدا نشد</translation> + </message> + <message> + <source>In use</source> + <translation>در حال استفاده</translation> + </message> + <message> + <source>Not ready</source> + <translation>آماده نیست</translation> + </message> + <message> + <source>Access denied</source> + <translation>دسترسی رد شد</translation> + </message> + <message> + <source>Could not connect</source> + <translation>عدم امکان اتصال</translation> + </message> + <message> + <source>Disconnected</source> + <translation>اتصال قطع شد</translation> + </message> + <message> + <source>Permission denied</source> + <translation>اجازه دسترسی رد شد</translation> + </message> + <message> + <source>Insufficient bandwidth</source> + <translation>پهنای باند ناکافی</translation> + </message> + <message> + <source>Network unavailable</source> + <translation>شبکه موجود نمیباشد</translation> + </message> + <message> + <source>Network communication error</source> + <translation>خطای اتصال به شبکه</translation> + </message> + <message> + <source>Streaming not supported</source> + <translation>جریاندهی پشتیبانی نشده است</translation> + </message> + <message> + <source>Server alert</source> + <translation>اخطار سرور</translation> + </message> + <message> + <source>Invalid protocol</source> + <translation>پروتکل نامعتبر</translation> + </message> + <message> + <source>Invalid URL</source> + <translation>URL نامعتبر</translation> + </message> + <message> + <source>Multicast error</source> + <translation>خطای قالببندی چندگانه</translation> + </message> + <message> + <source>Proxy server error</source> + <translation>خطای سرویسدهنده پروکسی</translation> + </message> + <message> + <source>Proxy server not supported</source> + <translation>سرویسدهنده پروکسی پشتیبانی نشده است</translation> + </message> + <message> + <source>Audio output error</source> + <translation>خطای خروجی صدا</translation> + </message> + <message> + <source>Video output error</source> + <translation>خطای خروجی تصویر</translation> + </message> + <message> + <source>Decoder error</source> + <translation>خطای رمزگشا</translation> + </message> + <message> + <source>Audio or video components could not be played</source> + <translation>اجزای صوتی یا تصویری نمیتوانند اجرا شوند</translation> + </message> + <message> + <source>DRM error</source> + <translation>خطای DRM</translation> + </message> + <message> + <source>Unknown error (%1)</source> + <translation>خطای ناشناخته (%1)</translation> + </message> +</context> +<context> + <name>Phonon::MMF::AbstractMediaPlayer</name> + <message> + <source>Not ready to play</source> + <translation>عدم آمادگی برای اجرا</translation> + </message> + <message> + <source>Error opening file</source> + <translation>خطای باز کردن پرونده</translation> + </message> + <message> + <source>Error opening URL</source> + <translation>خطای باز کردن URL</translation> + </message> + <message> + <source>Error opening resource</source> + <translation>خطای باز کردن منبع</translation> + </message> + <message> + <source>Error opening source: resource not opened</source> + <translation>خطای باز کردن منبع: منبع باز نشد</translation> + </message> + <message> + <source>Setting volume failed</source> + <translation>تنظیم حجم صدا انجام نشد</translation> + </message> + <message> + <source>Loading clip failed</source> + <translation>بارگذاری نماهنگ انجام نشد</translation> + </message> + <message> + <source>Playback complete</source> + <translation>پخش کامل شد</translation> + </message> + <message> + <source>Download error</source> + <translation>خطای دانلود</translation> + </message> +</context> +<context> + <name>Phonon::MMF::AbstractVideoPlayer</name> + <message> + <source>Pause failed</source> + <translation>توقف ناموفق</translation> + </message> + <message> + <source>Seek failed</source> + <translation>لغزش ناموفق</translation> + </message> + <message> + <source>Getting position failed</source> + <translation>بازیابی ناموفق موقعیت</translation> + </message> + <message> + <source>Opening clip failed</source> + <translation>باز کردن ناموفق نماهنگ</translation> + </message> +</context> +<context> + <name>Phonon::MMF::AudioEqualizer</name> + <message> + <source>%1 Hz</source> + <translation>%1 Hz</translation> + </message> +</context> +<context> + <name>Phonon::MMF::AudioPlayer</name> + <message> + <source>Getting position failed</source> + <translation>بازیابی ناموفق موقعیت</translation> + </message> +</context> +<context> + <name>Phonon::MMF::DsaVideoPlayer</name> + <message> + <source>Video display error</source> + <translation>خطای نمایش ویدیو</translation> + </message> +</context> +<context> + <name>Phonon::MMF::EffectFactory</name> + <message> + <source>Enabled</source> + <translation>فعال شد</translation> + </message> +</context> +<context> + <name>Phonon::MMF::EnvironmentalReverb</name> + <message> + <source>Decay HF ratio (%)</source> + <extracomment>DecayHFRatio: Ratio of high-frequency decay time to the value specified by DecayTime.</extracomment> + <translation>ضعیف شدن نسبت HF (٪)</translation> + </message> + <message> + <source>Decay time (ms)</source> + <extracomment>DecayTime: Time over which reverberation is diminished.</extracomment> + <translatorcomment>زمانی که طول میکشد تا پژواک موج تقلیل یابد</translatorcomment> + <translation>زمان کاهش یافتن (میلیثانیه)</translation> + </message> + <message> + <source>Density (%)</source> + <extracomment>Density Delay between first and subsequent reflections. Note that the S60 platform documentation does not make clear the distinction between this value and the Diffusion value.</extracomment> + <translatorcomment>تأخیر تراکم میان انعکاس اول و انعکاس بعدی. توجه کنید که مستندات پلتفرم S60 فرق میان این مقدار و مقدار نفوذ را مشخص نمیکند.</translatorcomment> + <translation>تراکم (٪)</translation> + </message> + <message> + <source>Diffusion (%)</source> + <extracomment>Diffusion: Delay between first and subsequent reflections. Note that the S60 platform documentation does not make clear the distinction between this value and the Density value.</extracomment> + <translatorcomment>تأخیر نفوذ میان انعکاس اول و انعکاس بعدی. توجه کنید که مستندات پلتفرم S60 فرق میان این مقدار و مقدار انعکاس را مشخص نمیکند.</translatorcomment> + <translation>نفوذ (٪)</translation> + </message> + <message> + <source>Reflections delay (ms)</source> + <extracomment>ReflectionsDelay: Amount of delay between the arrival the direct path from the source and the arrival of the first reflection.</extracomment> + <translation>تأخیر بازتابها (میلیثانیه)</translation> + </message> + <message> + <source>Reflections level (mB)</source> + <extracomment>ReflectionsLevel: Amplitude of reflections. This value is corrected by the RoomLevel to give the final reflection amplitude.</extracomment> + <translation>سطح بازتابها (میلیبل)</translation> + </message> + <message> + <source>Reverb delay (ms)</source> + <extracomment>ReverbDelay: Amount of time between arrival of the first reflection and start of the late reverberation.</extracomment> + <translation>تأخیر انعکاس(میلیثانیه)</translation> + </message> + <message> + <source>Reverb level (mB)</source> + <extracomment>ReverbLevel Amplitude of reverberations. This value is corrected by the RoomLevel to give the final reverberation amplitude.</extracomment> + <translation>سطح انعکاس (میلیبل)</translation> + </message> + <message> + <source>Room HF level</source> + <extracomment>RoomHFLevel: Amplitude of low-pass filter used to attenuate the high frequency component of reflected sound.</extracomment> + <translation>سطح HF فضا</translation> + </message> + <message> + <source>Room level (mB)</source> + <extracomment>RoomLevel: Master volume control for all reflected sound.</extracomment> + <translation>سطح فضا (میلیبل)</translation> + </message> +</context> +<context> + <name>Phonon::MMF::MediaObject</name> + <message> + <source>Error opening source: type not supported</source> + <translation>خطای باز کردن منبع: نوع پشتیبانی نشده</translation> + </message> + <message> + <source>Error opening source: resource is compressed</source> + <translation>خطای باز کردن منبع: منبع فشرده شده است</translation> + </message> + <message> + <source>Error opening source: resource not valid</source> + <translation>خطای باز کردن منبع: منبع نامعتبر است</translation> + </message> + <message> + <source>Error opening source: media type could not be determined</source> + <translation>خطای باز کردن منبع: نمیتوان نوع رسانه را تعیین کرد</translation> + </message> + <message> + <source>Failed to set requested IAP</source> + <translation>نمیتوان IAP درخواست شده را تنظیم کرد</translation> + </message> +</context> +<context> + <name>Phonon::MMF::StereoWidening</name> + <message> + <source>Level (%)</source> + <translation>سطح (%)</translation> + </message> +</context> +<context> + <name>Phonon::MMF::SurfaceVideoPlayer</name> + <message> + <source>Video display error</source> + <translation>خطای نمایش ویدیو</translation> + </message> +</context> +<context> + <name>Phonon::VolumeSlider</name> + <message> + <source>Volume: %1%</source> + <translation>حجم صدا:%1%</translation> + </message> + <message> + <source>Use this slider to adjust the volume. The leftmost position is 0%, the rightmost is %1%</source> + <translation>این لغزنده را برای تنظیم صدا استفاده کنید. سمت چپترین حالت %، سمت راستترین حالت %1%</translation> + </message> + <message> + <source>Muted</source> + <translation>مات</translation> + </message> +</context> +<context> + <name>Q3Accel</name> + <message> + <source>%1, %2 not defined</source> + <translation>%1، %2 تعریف نشده</translation> + </message> + <message> + <source>Ambiguous %1 not handled</source> + <translation>ابهام %1 برطرف نشده</translation> + </message> +</context> +<context> + <name>Q3DataTable</name> + <message> + <source>True</source> + <translation>درست</translation> + </message> + <message> + <source>False</source> + <translation>نادرست</translation> + </message> + <message> + <source>Insert</source> + <translation>درج</translation> + </message> + <message> + <source>Update</source> + <translation>بهروزرسانی</translation> + </message> + <message> + <source>Delete</source> + <translation>حذف</translation> + </message> +</context> +<context> + <name>Q3FileDialog</name> + <message> + <source>Copy or Move a File</source> + <translation>کپی با جابهجایی یک پرونده</translation> + </message> + <message> + <source>Read: %1</source> + <translation>خواندن: %1</translation> + </message> + <message> + <source>Write: %1</source> + <translation>نوشتن: %1</translation> + </message> + <message> + <source>Cancel</source> + <translation>لغو</translation> + </message> + <message> + <source>All Files (*)</source> + <translation>تمام پروندهها (*)</translation> + </message> + <message> + <source>Name</source> + <translation>نام</translation> + </message> + <message> + <source>Size</source> + <translation>حجم</translation> + </message> + <message> + <source>Type</source> + <translation>نوع</translation> + </message> + <message> + <source>Date</source> + <translation>تاریخ</translation> + </message> + <message> + <source>Attributes</source> + <translation>ویژگیها</translation> + </message> + <message> + <source>&OK</source> + <translation>&تأیید</translation> + </message> + <message> + <source>Look &in:</source> + <translation>جستجو &در:</translation> + </message> + <message> + <source>File &name:</source> + <translation>&نام پرونده:</translation> + </message> + <message> + <source>File &type:</source> + <translation>&نوع پرونده:</translation> + </message> + <message> + <source>Back</source> + <translation>عقب</translation> + </message> + <message> + <source>One directory up</source> + <translation>یک پوشه بالاتر</translation> + </message> + <message> + <source>Create New Folder</source> + <translation>ایجاد پوشه جدید</translation> + </message> + <message> + <source>List View</source> + <translation>نمایش سیاهه</translation> + </message> + <message> + <source>Detail View</source> + <translation>نمایش جزئیات</translation> + </message> + <message> + <source>Preview File Info</source> + <translation>مشاهده اطلاعات پرونده</translation> + </message> + <message> + <source>Preview File Contents</source> + <translation>مشاهده محتویات پرونده</translation> + </message> + <message> + <source>Read-write</source> + <translation>خواندن-نوشتن</translation> + </message> + <message> + <source>Read-only</source> + <translation>فقط-خواندنی</translation> + </message> + <message> + <source>Write-only</source> + <translation>فقط-نوشتنی</translation> + </message> + <message> + <source>Inaccessible</source> + <translation>غیر قابل دسترس</translation> + </message> + <message> + <source>Symlink to File</source> + <translation>لینک سمبلیک به فایل</translation> + </message> + <message> + <source>Symlink to Directory</source> + <translation>لینک سمبلیک به پوشه</translation> + </message> + <message> + <source>Symlink to Special</source> + <translation>لینک سمبلیک خاص</translation> + </message> + <message> + <source>File</source> + <translation>پرونده</translation> + </message> + <message> + <source>Dir</source> + <translation>مسیر</translation> + </message> + <message> + <source>Special</source> + <translation>ویژه</translation> + </message> + <message> + <source>Open</source> + <translation>باز کردن</translation> + </message> + <message> + <source>Save As</source> + <translation>ذخیره به عنوان</translation> + </message> + <message> + <source>&Open</source> + <translation>&بازکردن</translation> + </message> + <message> + <source>&Save</source> + <translation>&ذخیره</translation> + </message> + <message> + <source>&Rename</source> + <translation>&تغییر نام</translation> + </message> + <message> + <source>&Delete</source> + <translation>&حذف</translation> + </message> + <message> + <source>R&eload</source> + <translation>بارگذاری &مجدد</translation> + </message> + <message> + <source>Sort by &Name</source> + <translation>مرتبسازی بر حسب &نام</translation> + </message> + <message> + <source>Sort by &Size</source> + <translation>مرتبسازی بر حسب &اندازه</translation> + </message> + <message> + <source>Sort by &Date</source> + <translation>مرتبسازی بر حسب &تاریخ</translation> + </message> + <message> + <source>&Unsorted</source> + <translation>.&مرتب نشده</translation> + </message> + <message> + <source>Sort</source> + <translation>مرتبسازی</translation> + </message> + <message> + <source>Show &hidden files</source> + <translation>نمایش پروندههای م&خفی</translation> + </message> + <message> + <source>the file</source> + <translation>پرونده</translation> + </message> + <message> + <source>the directory</source> + <translation>پوشه</translation> + </message> + <message> + <source>the symlink</source> + <translation>لینک سمبلیک</translation> + </message> + <message> + <source>Delete %1</source> + <translation>حذف %1</translation> + </message> + <message> + <source><qt>Are you sure you wish to delete %1 "%2"?</qt></source> + <translation><qt>آیا مطمئن هستید که میخواهید حذف کنید %1 "%2"?</qt></translation> + </message> + <message> + <source>&Yes</source> + <translation>&بله</translation> + </message> + <message> + <source>&No</source> + <translation>&نه</translation> + </message> + <message> + <source>New Folder 1</source> + <translation>پوشهٔ جدید ۱</translation> + </message> + <message> + <source>New Folder</source> + <translation>پوشهٔ جدید</translation> + </message> + <message> + <source>New Folder %1</source> + <translation>پوشهٔ جدید %1</translation> + </message> + <message> + <source>Find Directory</source> + <translation>پیدا کردن پوشه</translation> + </message> + <message> + <source>Directories</source> + <translation>پوشهها</translation> + </message> + <message> + <source>Directory:</source> + <translation>پوشه:</translation> + </message> + <message> + <source>Error</source> + <translation>خطا</translation> + </message> + <message> + <source>%1 +File not found. +Check path and filename.</source> + <translation>%1 +پرونده پیدا نشد +مسیر و نام پرونده را بررسی کنید.</translation> + </message> + <message> + <source>All Files (*.*)</source> + <translation>تمام پروندهها (*.*)</translation> + </message> + <message> + <source>Open </source> + <translation>بازکردن</translation> + </message> + <message> + <source>Select a Directory</source> + <translation>انتخاب یک پوشه</translation> + </message> +</context> +<context> + <name>Q3LocalFs</name> + <message> + <source>Could not read directory +%1</source> + <translation>نمیتوان پوشه +%1 +را خواند</translation> + </message> + <message> + <source>Could not create directory +%1</source> + <translation>نمیتوان پوشه +%1 +را ایجاد کرد</translation> + </message> + <message> + <source>Could not remove file or directory +%1</source> + <translation>نمیتوان پوشه یا پرونده +%1 +را پاک کرد</translation> + </message> + <message> + <source>Could not rename +%1 +to +%2</source> + <translation>نمیتوان + %1 +را به +%2 +تغییر نام داد</translation> + </message> + <message> + <source>Could not open +%1</source> + <translation>نمیتوان باز کرد +%1</translation> + </message> + <message> + <source>Could not write +%1</source> + <translation>نمیتوان در +%1 +نوشت</translation> + </message> +</context> +<context> + <name>Q3MainWindow</name> + <message> + <source>Line up</source> + <translation>به خط شدن</translation> + </message> + <message> + <source>Customize...</source> + <translation>سفارشی کردن...</translation> + </message> +</context> +<context> + <name>Q3NetworkProtocol</name> + <message> + <source>Operation stopped by the user</source> + <translation>عملیات توسط کاربر متوقف شد</translation> + </message> +</context> +<context> + <name>Q3ProgressDialog</name> + <message> + <source>Cancel</source> + <translation>لغو</translation> + </message> +</context> +<context> + <name>Q3TabDialog</name> + <message> + <source>OK</source> + <translation>تأیید</translation> + </message> + <message> + <source>Apply</source> + <translation>اعمال.کردن</translation> + </message> + <message> + <source>Help</source> + <translation>کمک</translation> + </message> + <message> + <source>Defaults</source> + <translation>پیشفرضها</translation> + </message> + <message> + <source>Cancel</source> + <translation>لغو</translation> + </message> +</context> +<context> + <name>Q3TextEdit</name> + <message> + <source>&Undo</source> + <translation>&خنثیسازی</translation> + </message> + <message> + <source>&Redo</source> + <translation>&بازانجام</translation> + </message> + <message> + <source>Cu&t</source> + <translation>&برش</translation> + </message> + <message> + <source>&Copy</source> + <translation>&کپی</translation> + </message> + <message> + <source>&Paste</source> + <translation>&چسباندن</translation> + </message> + <message> + <source>Clear</source> + <translation>پاک کردن</translation> + </message> + <message> + <source>Select All</source> + <translation>انتخاب همه</translation> + </message> +</context> +<context> + <name>Q3TitleBar</name> + <message> + <source>System</source> + <translation>سیستم</translation> + </message> + <message> + <source>Restore up</source> + <translation>بازیابی به بالا</translation> + </message> + <message> + <source>Minimize</source> + <translation>کوچک کردن</translation> + </message> + <message> + <source>Restore down</source> + <translation>بازیابی به پایین</translation> + </message> + <message> + <source>Maximize</source> + <translation>بزرگ کردن</translation> + </message> + <message> + <source>Close</source> + <translation>بستن</translation> + </message> + <message> + <source>Contains commands to manipulate the window</source> + <translation>حاوی دستوراتی برای دستکاری پنجره است</translation> + </message> + <message> + <source>Puts a minimized window back to normal</source> + <translation>پنجره کوچک شده را به اندازه عادی برمیگرداند</translation> + </message> + <message> + <source>Moves the window out of the way</source> + <translation>پنجره را به خارج از مسیر میبرد</translation> + </message> + <message> + <source>Puts a maximized window back to normal</source> + <translation>پنجرهٔ بزرگ شده را به اندازه عادی برمیگرداند</translation> + </message> + <message> + <source>Makes the window full screen</source> + <translation>پنجره را تمام صفحه میکند</translation> + </message> + <message> + <source>Closes the window</source> + <translation>پنجره را میبندد</translation> + </message> + <message> + <source>Displays the name of the window and contains controls to manipulate it</source> + <translation>نام پنجره را نمایش میدهد و حاوی کنترلهایی برای دستکاری آن است</translation> + </message> +</context> +<context> + <name>Q3ToolBar</name> + <message> + <source>More...</source> + <translation>بیشتر...</translation> + </message> +</context> +<context> + <name>Q3UrlOperator</name> + <message> + <source>The protocol `%1' is not supported</source> + <translation>پروتکل «%1» پشتیبانی نشده است</translation> + </message> + <message> + <source>The protocol `%1' does not support listing directories</source> + <translation>پروتکل «%1» سیاههبرداری پوشهها را پشتیبانی نمیکند</translation> + </message> + <message> + <source>The protocol `%1' does not support creating new directories</source> + <translation>پروتکل «%1» ایجاد کردن پوشههای جدید را پشتیبانی نمیکند</translation> + </message> + <message> + <source>The protocol `%1' does not support removing files or directories</source> + <translation>پروتکل «%1» پاک کردن پروندهها یا پوشهها را پشتیبانی نمیکند</translation> + </message> + <message> + <source>The protocol `%1' does not support renaming files or directories</source> + <translation>پروتکل «%1» تغییر نام پروندهها یا پوشهها را پشتیبانی نمیکند</translation> + </message> + <message> + <source>The protocol `%1' does not support getting files</source> + <translation>پروتکل «%1» گرفتن پروندهها را پشتیبانی نمیکند</translation> + </message> + <message> + <source>The protocol `%1' does not support putting files</source> + <translation>پروتکل «%1» ثبت کردن پروندهها را پشتیبانی نمیکند</translation> + </message> + <message> + <source>The protocol `%1' does not support copying or moving files or directories</source> + <translation>پروتکل «%1» کپی یا انتقال پروندهها یا پوشهها را پشتیبانی نمیکند</translation> + </message> + <message> + <source>(unknown)</source> + <translation>(ناشناخته)</translation> + </message> +</context> +<context> + <name>Q3Wizard</name> + <message> + <source>&Cancel</source> + <translation>&لغو</translation> + </message> + <message> + <source>< &Back</source> + <translation>< &عقب</translation> + </message> + <message> + <source>&Next ></source> + <translation>بع&دی ></translation> + </message> + <message> + <source>&Finish</source> + <translation>پایا&ن</translation> + </message> + <message> + <source>&Help</source> + <translation>&کمک</translation> + </message> +</context> +<context> + <name>QAbstractSocket</name> + <message> + <source>Socket operation timed out</source> + <translation>پایان زمان عملیات سوکت</translation> + </message> + <message> + <source>Operation on socket is not supported</source> + <translation>عملیات روی سوکت پشتیبانی نمیشود</translation> + </message> + <message> + <source>Host not found</source> + <translation>میزبان یافت نشد</translation> + </message> + <message> + <source>Connection refused</source> + <translation>اتصال پذیرفته نشد</translation> + </message> + <message> + <source>Connection timed out</source> + <translation>پایان زمان اتصال</translation> + </message> + <message> + <source>Socket is not connected</source> + <translation>سوکت متصل نیست</translation> + </message> + <message> + <source>Network unreachable</source> + <translation>شبکه در دسترس نیست</translation> + </message> +</context> +<context> + <name>QAbstractSpinBox</name> + <message> + <source>&Select All</source> + <translation>انتخاب &همه</translation> + </message> + <message> + <source>&Step up</source> + <translation>&افزایش</translation> + </message> + <message> + <source>Step &down</source> + <translation>&کاهش</translation> + </message> +</context> +<context> + <name>QAccessibleButton</name> + <message> + <source>Press</source> + <translation>فشار دادن</translation> + </message> +</context> +<context> + <name>QApplication</name> + <message> + <source>Activate</source> + <translation>فعالسازی</translation> + </message> + <message> + <source>Activates the program's main window</source> + <translation>پنجره اصلی برنامه را فعال میکند</translation> + </message> + <message> + <source>Executable '%1' requires Qt %2, found Qt %3.</source> + <translation>برنامهٔ «%1»نیازمند کیوت %2 است، کیوت %3 یافت شد.</translation> + </message> + <message> + <source>Incompatible Qt Library Error</source> + <translation>خطای کتابخانه ناسازگار کیوت</translation> + </message> + <message> + <source>QT_LAYOUT_DIRECTION</source> + <comment>Translate this string to the string 'LTR' in left-to-right languages or to 'RTL' in right-to-left languages (such as Hebrew and Arabic) to get proper widget layout.</comment> + <translation>RTL</translation> + </message> +</context> +<context> + <name>QAxSelect</name> + <message> + <source>Select ActiveX Control</source> + <translation>انتخاب کنترل ActiveX</translation> + </message> + <message> + <source>OK</source> + <translation>تأیید</translation> + </message> + <message> + <source>&Cancel</source> + <translation>&لغو</translation> + </message> + <message> + <source>COM &Object:</source> + <translation>شیء &COM:</translation> + </message> +</context> +<context> + <name>QCheckBox</name> + <message> + <source>Uncheck</source> + <translation>عدم انتخاب</translation> + </message> + <message> + <source>Check</source> + <translation>انتخاب</translation> + </message> + <message> + <source>Toggle</source> + <translation>ضامن</translation> + </message> +</context> +<context> + <name>QColorDialog</name> + <message> + <source>Hu&e:</source> + <translation>&شدت:</translation> + </message> + <message> + <source>&Sat:</source> + <translation>اشبا&ع:</translation> + </message> + <message> + <source>&Val:</source> + <translation>م&قدار:</translation> + </message> + <message> + <source>&Red:</source> + <translation>&قرمز:</translation> + </message> + <message> + <source>&Green:</source> + <translation>&سبز:</translation> + </message> + <message> + <source>Bl&ue:</source> + <translation>&آبی:</translation> + </message> + <message> + <source>A&lpha channel:</source> + <translation>&کانال آلفا:</translation> + </message> + <message> + <source>Select Color</source> + <translation>انتخاب رنگ</translation> + </message> + <message> + <source>&Basic colors</source> + <translation>رن&گهای پایه</translation> + </message> + <message> + <source>&Custom colors</source> + <translation>رنگهای &سفارشی</translation> + </message> + <message> + <source>&Add to Custom Colors</source> + <translation>&افزودن به رنگهای سفارشی</translation> + </message> +</context> +<context> + <name>QComboBox</name> + <message> + <source>False</source> + <translation>نادرست</translation> + </message> + <message> + <source>True</source> + <translation>درست</translation> + </message> + <message> + <source>Open</source> + <translation>باز کردن</translation> + </message> + <message> + <source>Close</source> + <translation>بستن</translation> + </message> +</context> +<context> + <name>QCoreApplication</name> + <message> + <source>%1: already exists</source> + <comment>QSystemSemaphore</comment> + <translation>%1: از قبل وجود دارد</translation> + </message> + <message> + <source>%1: does not exist</source> + <comment>QSystemSemaphore</comment> + <translation>%1: وجود ندارد</translation> + </message> + <message> + <source>%1: out of resources</source> + <comment>QSystemSemaphore</comment> + <translation>%1: خارج از منابع</translation> + </message> + <message> + <source>%1: permission denied</source> + <comment>QSystemSemaphore</comment> + <translation>%1:اجازه رد شد</translation> + </message> + <message> + <source>%1: unknown error %2</source> + <comment>QSystemSemaphore</comment> + <translation>%1: خطای ناشناخته %2</translation> + </message> + <message> + <source>%1: key is empty</source> + <comment>QSystemSemaphore</comment> + <translation>%1: کلید تهی است</translation> + </message> + <message> + <source>%1: unable to make key</source> + <comment>QSystemSemaphore</comment> + <translation>%1: نمیتوان کلید ایجاد کرد</translation> + </message> + <message> + <source>%1: ftok failed</source> + <comment>QSystemSemaphore</comment> + <translation>%1: عدم موفقیت ftok</translation> + </message> +</context> +<context> + <name>QDB2Driver</name> + <message> + <source>Unable to connect</source> + <translation>نمیتوان اتصال برقرار کرد</translation> + </message> + <message> + <source>Unable to commit transaction</source> + <translation>نمیتوان تراکنش را ارسال کرد</translation> + </message> + <message> + <source>Unable to rollback transaction</source> + <translation>نمیتوان تراکنش را بازگرداند</translation> + </message> + <message> + <source>Unable to set autocommit</source> + <translation>نمیتوان ارسال خودکار را برقرار کرد</translation> + </message> +</context> +<context> + <name>QDB2Result</name> + <message> + <source>Unable to execute statement</source> + <translation>نمیتوان عبارت را اجرا کرد</translation> + </message> + <message> + <source>Unable to prepare statement</source> + <translation>نمیتوان عبارت را آماده کرد</translation> + </message> + <message> + <source>Unable to bind variable</source> + <translation>نمیتوان متغیر را مقید کرد</translation> + </message> + <message> + <source>Unable to fetch record %1</source> + <translation>نمیتوان رکورد %1 را واکشی کرد</translation> + </message> + <message> + <source>Unable to fetch next</source> + <translation>نمیتوان رکورد بعدی را واکشی کرد</translation> + </message> + <message> + <source>Unable to fetch first</source> + <translation>نمیتوان اولین رکورد را واکشی کرد</translation> + </message> +</context> +<context> + <name>QDateTimeEdit</name> + <message> + <source>AM</source> + <translation>قظ</translation> + </message> + <message> + <source>am</source> + <translation>قظ</translation> + </message> + <message> + <source>PM</source> + <translation>بظ</translation> + </message> + <message> + <source>pm</source> + <translation>بظ</translation> + </message> +</context> +<context> + <name>QDeclarativeAbstractAnimation</name> + <message> + <source>Cannot animate non-existent property "%1"</source> + <translation>نمیتوان ویژگی ناموجود %1 را متحرک سازی کرد</translation> + </message> + <message> + <source>Cannot animate read-only property "%1"</source> + <translation>نمیتوان ویژگی فقط خواندنی %1 را متحرک کرد</translation> + </message> + <message> + <source>Animation is an abstract class</source> + <translation>Animation یک کلاس انتزاعی است</translation> + </message> +</context> +<context> + <name>QDeclarativeAnchorAnimation</name> + <message> + <source>Cannot set a duration of < 0</source> + <translation>نمیتوان مدت زمانی کمتر از صفر را قرار داد</translation> + </message> +</context> +<context> + <name>QDeclarativeAnchors</name> + <message> + <source>Possible anchor loop detected on fill.</source> + <translation>حلقهٔ احتمالی تکیهگاه در «پر» تشخیص داده شد.</translation> + </message> + <message> + <source>Possible anchor loop detected on centerIn.</source> + <translation>حلقهٔ احتمالی تکیهگاه در «مرکز-داخل» تشخیص داده شد.</translation> + </message> + <message> + <source>Cannot anchor to an item that isn't a parent or sibling.</source> + <translation>نمیتوان به آیتمی که والد یا هم نوع نیست لنگر انداخت.</translation> + </message> + <message> + <source>Possible anchor loop detected on vertical anchor.</source> + <translation>گره ممکنهٔ محکم کردن روی حالت عمودی گرفته شد.</translation> + </message> + <message> + <source>Possible anchor loop detected on horizontal anchor.</source> + <translation>حلقهٔ احتمالی تکیهگاه در تکیهگاه «افقی» تشخیص داده شد.</translation> + </message> + <message> + <source>Cannot specify left, right, and hcenter anchors.</source> + <translation>نمیتوان تکیه گاه چپ ، راست و افقی-مرکزی معین کرد.</translation> + </message> + <message> + <source>Cannot anchor to a null item.</source> + <translation>نمیتوان به یک آیتم تهی لنگر انداخت.</translation> + </message> + <message> + <source>Cannot anchor a horizontal edge to a vertical edge.</source> + <translation>نمیتوان یک یال افقی را به یک یال عمودی تکیه داد.</translation> + </message> + <message> + <source>Cannot anchor item to self.</source> + <translation>نمیتوان یک آیتم را به خودش تکیه داد.</translation> + </message> + <message> + <source>Cannot specify top, bottom, and vcenter anchors.</source> + <translation>نمیتوان تکیهگاه بالا، کف و عمودی-مرکزی معین کرد.</translation> + </message> + <message> + <source>Baseline anchor cannot be used in conjunction with top, bottom, or vcenter anchors.</source> + <translation>تکیهگاه خط مبنا نمیتواند در اتصالات بالا ، کف و عمودی-مرکزی استفاده شود.</translation> + </message> + <message> + <source>Cannot anchor a vertical edge to a horizontal edge.</source> + <translation>نمیتوان یک یال عمودی را به یک یال افقی تکیه داد.</translation> + </message> +</context> +<context> + <name>QDeclarativeAnimatedImage</name> + <message> + <source>Qt was built without support for QMovie</source> + <translation>Qt بدون پشتیبانی از QMovie ساخته شده است</translation> + </message> +</context> +<context> + <name>QDeclarativeApplication</name> + <message> + <source>Application is an abstract class</source> + <translation>Application یک کلاس مجرد است</translation> + </message> +</context> +<context> + <name>QDeclarativeBehavior</name> + <message> + <source>Cannot change the animation assigned to a Behavior.</source> + <translation>نمیتوان انیمیشنی را که به رفتار اختصاص یافته تغییر داد.</translation> + </message> +</context> +<context> + <name>QDeclarativeBinding</name> + <message> + <source>Binding loop detected for property "%1"</source> + <translation>حلقهٔ مقیدسازی برای ویژگی «%1» تشخیص داده شد</translation> + </message> +</context> +<context> + <name>QDeclarativeCompiledBindings</name> + <message> + <source>Binding loop detected for property "%1"</source> + <translation>حلقهٔ مقیدسازی برای ویژگی "%1" تشخیص داده شد</translation> + </message> +</context> +<context> + <name>QDeclarativeCompiler</name> + <message> + <source>Invalid property assignment: "%1" is a read-only property</source> + <translation>تخصیص نامعتبر ویژگی: «%1» ویژگی فقط خواندنی است</translation> + </message> + <message> + <source>Invalid property assignment: unknown enumeration</source> + <translation>تخصیص نامعتبر ویژگی: شمارش ناشناخته</translation> + </message> + <message> + <source>Invalid property assignment: string expected</source> + <translation>تخصیص نامعتبر ویژگی: رشته مورد انتظار است</translation> + </message> + <message> + <source>Invalid property assignment: url expected</source> + <translation>تخصیص نامعتبر ویژگی: url مورد انتظار است</translation> + </message> + <message> + <source>Invalid property assignment: unsigned int expected</source> + <translation>تخصیص نامعتبر ویژگی: نوع unsigned int مورد انتظار است</translation> + </message> + <message> + <source>Invalid property assignment: int expected</source> + <translation>تخصیص نامعتبر ویژگی: نوع int مورد انتظار است</translation> + </message> + <message> + <source>Invalid property assignment: number expected</source> + <translation>تخصیص نامعتبر ویژگی: number مورد انتظار است</translation> + </message> + <message> + <source>Invalid property assignment: color expected</source> + <translation>تخصیص نامعتبر ویژگی: color مورد انتظار است</translation> + </message> + <message> + <source>Invalid property assignment: date expected</source> + <translation>تخصیص نامعتبر ویژگی: date مورد انتظار است</translation> + </message> + <message> + <source>Invalid property assignment: time expected</source> + <translation>تخصیص نامعتبر ویژگی: نوع time مورد انتظار است</translation> + </message> + <message> + <source>Invalid property assignment: datetime expected</source> + <translation>تخصیص نامعتبر ویژگی: نوع datetime مورد انتظار است</translation> + </message> + <message> + <source>Invalid property assignment: point expected</source> + <translation>تخصیص نامعتبر ویژگی: point مورد انتظار است</translation> + </message> + <message> + <source>Invalid property assignment: size expected</source> + <translation>تخصیص نامعتبر ویژگی: size مورد انتظار است</translation> + </message> + <message> + <source>Invalid property assignment: rect expected</source> + <translation>تخصیص نامعتبر ویژگی: rect مورد انتظار است</translation> + </message> + <message> + <source>Invalid property assignment: boolean expected</source> + <translation>تخصیص نامعتبر ویژگی: boolean مورد انتظار است</translation> + </message> + <message> + <source>Invalid property assignment: 3D vector expected</source> + <translation>تخصیص نامعتبر ویژگی: 3D vector مورد انتظار است</translation> + </message> + <message> + <source>Invalid property assignment: unsupported type "%1"</source> + <translation>تخصیص نامعتبر ویژگی: نوع پشتیبانی نشده «%1»</translation> + </message> + <message> + <source>Element is not creatable.</source> + <translation>عنصر قابل ایجاد نیست.</translation> + </message> + <message> + <source>Component elements may not contain properties other than id</source> + <translation>عناصر کامپوننت نمیتوانند دربردارنده ویژگیهایی به غیر از شناسه باشند</translation> + </message> + <message> + <source>Invalid component id specification</source> + <translation>مشخصه نامعتبر شناسه کامپوننت</translation> + </message> + <message> + <source>id is not unique</source> + <translation>شناسه یکتا نیست</translation> + </message> + <message> + <source>Invalid component body specification</source> + <translation>مشخصه نامعتبر بدنه کامپوننت</translation> + </message> + <message> + <source>Component objects cannot declare new properties.</source> + <translation>اشیاء کامپوننت نمیتوانند ویژگیهای جدید اعلان کنند.</translation> + </message> + <message> + <source>Component objects cannot declare new signals.</source> + <translation>اشیاء کامپوننت نمیتوانند سیگنالهای جدید اعلان کنند.</translation> + </message> + <message> + <source>Component objects cannot declare new functions.</source> + <translation>اشیاء کامپوننت نمیتوانند توابع جدید تعریف کند.</translation> + </message> + <message> + <source>Cannot create empty component specification</source> + <translation>نمیتوان مشخصه خالی کامپوننت ایجاد کرد</translation> + </message> + <message> + <source>"%1.%2" is not available in %3 %4.%5.</source> + <translation>«%1.%2» در %3 %4.%5 موجود نمیباشد.</translation> + </message> + <message> + <source>"%1.%2" is not available due to component versioning.</source> + <translation>«%1.%2» با توجه به نسخه کامپوننت در دسترس نیست.</translation> + </message> + <message> + <source>Incorrectly specified signal assignment</source> + <translation>تعیین نادرست تخصیص سیگنال</translation> + </message> + <message> + <source>Cannot assign a value to a signal (expecting a script to be run)</source> + <translation>نمیتوان یک مقدار را به یک سیگنال اختصاص داد (یک اسکریپت برای اجرا مورد نیاز است)</translation> + </message> + <message> + <source>Empty signal assignment</source> + <translation>تخصیص خالی سیگنال</translation> + </message> + <message> + <source>Empty property assignment</source> + <translation>تخصیص خالی ویژگی</translation> + </message> + <message> + <source>Attached properties cannot be used here</source> + <translation>ویژگیهای اتصال داده شده نمیتوانند اینجا استفاده شوند</translation> + </message> + <message> + <source>Non-existent attached object</source> + <translation>شیء اتصال داده شده ناموجود</translation> + </message> + <message> + <source>Invalid attached object assignment</source> + <translation>تخصیص نامعتبر شیء اتصال داده شده</translation> + </message> + <message> + <source>Cannot assign to non-existent default property</source> + <translation>نمیتوان به ویژگی پیشفرض ناموجود تخصیص داد</translation> + </message> + <message> + <source>Cannot assign to non-existent property "%1"</source> + <translation>نمیتوان ویژگی «%1» را به چیزی که وجود ندارد تخصیص داد</translation> + </message> + <message> + <source>Invalid use of namespace</source> + <translation>استفادهٔ نامعتبر از فضای نامی</translation> + </message> + <message> + <source>Not an attached property name</source> + <translation>نام یک ویژگی وابسته نیست</translation> + </message> + <message> + <source>Invalid use of id property</source> + <translation>استفاده نامعتبر از ویژگی شناسه</translation> + </message> + <message> + <source>Property has already been assigned a value</source> + <translation>از قبل به ویژگی یک مقدار اختصاص یافته است</translation> + </message> + <message> + <source>Invalid grouped property access</source> + <translation>دسترسی نامعتبر به ویژگی گروهی</translation> + </message> + <message> + <source>Cannot assign a value directly to a grouped property</source> + <translation>نمیتوان یک مقدار را به طور مستقیم به یک ویژگی گروهی اختصاص داد</translation> + </message> + <message> + <source>Invalid property use</source> + <translation>استفاده نامعتبر از ویژگی</translation> + </message> + <message> + <source>Property assignment expected</source> + <translation>اختصاص ویژگی مورد انتظار است</translation> + </message> + <message> + <source>Single property assignment expected</source> + <translation>اختصاص ویژگی تکی مورد انتظار است</translation> + </message> + <message> + <source>Unexpected object assignment</source> + <translation>اختصاص غیر منتظره شیء</translation> + </message> + <message> + <source>Cannot assign object to list</source> + <translation>نمیتوان به لیست شیء اختصاص داد</translation> + </message> + <message> + <source>Can only assign one binding to lists</source> + <translation>فقط یک قید را میتوان به شیء اختصاص داد</translation> + </message> + <message> + <source>Cannot assign primitives to lists</source> + <translation>نمیتوان انواع اولیه را به لیست اختصاص داد</translation> + </message> + <message> + <source>Cannot assign multiple values to a script property</source> + <translation>نمیتوان مقادیر مضاعف را به یک ویژگی اسکریپت اختصاص داد</translation> + </message> + <message> + <source>Invalid property assignment: script expected</source> + <translation>اختصاص نامعتبر ویژگی: اسکریپت مورد انتظار است</translation> + </message> + <message> + <source>Cannot assign multiple values to a singular property</source> + <translation>نمیتوان مقادیر چندگانه را به ویژگی یگانه نسبت داد</translation> + </message> + <message> + <source>Cannot assign object to property</source> + <translation>نمیتوان شیء به یک ویژگی اختصاص داد</translation> + </message> + <message> + <source>"%1" cannot operate on "%2"</source> + <translation>«%1» نمیتواند روی «%2» عمل کند</translation> + </message> + <message> + <source>Duplicate default property</source> + <translation>ویژگی پیشفرض تکراری</translation> + </message> + <message> + <source>Duplicate property name</source> + <translation>اسم ویژگی مضاعف</translation> + </message> + <message> + <source>Property names cannot begin with an upper case letter</source> + <translation>اسامی ویژگی نمیتوانند با حروف الفبای بزرگ شروع شوند</translation> + </message> + <message> + <source>Illegal property name</source> + <translation>نام غیرمجاز ویژگی</translation> + </message> + <message> + <source>Duplicate signal name</source> + <translation>نام تکی چندگانه</translation> + </message> + <message> + <source>Signal names cannot begin with an upper case letter</source> + <translation>اسامی سیگنالها نمیتوانند با حروف الفبای بزرگ شروع شوند</translation> + </message> + <message> + <source>Illegal signal name</source> + <translation>نام غیرمجاز سیگنال</translation> + </message> + <message> + <source>Duplicate method name</source> + <translation>نام تکراری متد</translation> + </message> + <message> + <source>Method names cannot begin with an upper case letter</source> + <translation>اسامی متدها نمیتوانند با حروف الفبای بزرگ شروع شوند</translation> + </message> + <message> + <source>Illegal method name</source> + <translation>نام غیرمجاز متد</translation> + </message> + <message> + <source>Property value set multiple times</source> + <translation>مقدار ویژگی چند بار تعیین شد</translation> + </message> + <message> + <source>Invalid property nesting</source> + <translation>تودرتویی غیر مجاز ویژگی</translation> + </message> + <message> + <source>Cannot override FINAL property</source> + <translation>نمیتوان ویژگی FINAL را لغو کرد</translation> + </message> + <message> + <source>Invalid property type</source> + <translation>نوع نامعتبر ویژگی</translation> + </message> + <message> + <source>Invalid empty ID</source> + <translation>شناسه خالی نامعتبر</translation> + </message> + <message> + <source>IDs cannot start with an uppercase letter</source> + <translation>شناسهها نمیتوانند با حروف الفبای بزرگ شروع شوند</translation> + </message> + <message> + <source>IDs must start with a letter or underscore</source> + <translation>شناسهها باید با یک حرف یا خط زیرین شروع شوند</translation> + </message> + <message> + <source>IDs must contain only letters, numbers, and underscores</source> + <translation>شناسهها فقط میتوانند شامل حرف ، عدد و خط زیرین باشند</translation> + </message> + <message> + <source>ID illegally masks global JavaScript property</source> + <translation>شناسه به طور غیرمجاز ویژگی JavaScript را پوشش میدهد</translation> + </message> + <message> + <source>No property alias location</source> + <translation>مکان نام مستعار ویژگی وجود ندارد</translation> + </message> + <message> + <source>Invalid alias location</source> + <translation>مکان نامعتبر نام مستعار</translation> + </message> + <message> + <source>Invalid alias reference. An alias reference must be specified as <id>, <id>.<property> or <id>.<value property>.<property></source> + <translation>ارجاع نامعتبر اسم مستعار.یک ارجاع نام مستعار باید به شکل <شناسه>, <شناسه>.<ویژگی> یا <id>.<مقدار ویژگی>.<ویژگی> مشخص شود</translation> + </message> + <message> + <source>Invalid alias reference. Unable to find id "%1"</source> + <translation>مرجع نامعتبر نام مستعار. ناتوان در یافتن شناسه «%1»</translation> + </message> + <message> + <source>Alias property exceeds alias bounds</source> + <translation>ویژگی نام مستعار از حدود مجاز تجاوز میکند</translation> + </message> +</context> +<context> + <name>QDeclarativeComponent</name> + <message> + <source>Invalid empty URL</source> + <translation>URL خالی نامعتبر</translation> + </message> + <message> + <source>createObject: value is not an object</source> + <translation>createObject: مقدار یک شیء نیست</translation> + </message> +</context> +<context> + <name>QDeclarativeConnections</name> + <message> + <source>Cannot assign to non-existent property "%1"</source> + <translation>نمیتوان به ویژگی ناموجود «%1» نسبت داد</translation> + </message> + <message> + <source>Connections: nested objects not allowed</source> + <translation>اتصالات: اشیاء تودرتو مجاز نیستند</translation> + </message> + <message> + <source>Connections: syntax error</source> + <translation>اتصالات: خطای نحوی</translation> + </message> + <message> + <source>Connections: script expected</source> + <translation>اتصالات: اسکریپت مورد انتظار است</translation> + </message> +</context> +<context> + <name>QDeclarativeEngine</name> + <message> + <source>executeSql called outside transaction()</source> + <translation>executeSql خارج از transaction() صدا زده شده است</translation> + </message> + <message> + <source>Read-only Transaction</source> + <translation>تراکنش فقط خواندنی</translation> + </message> + <message> + <source>Version mismatch: expected %1, found %2</source> + <translation>عدم تطابق نسخه: مورد انتظار: %1؛ پیدا شده: %2</translation> + </message> + <message> + <source>SQL transaction failed</source> + <translation>تراکنش ناموفق SQL</translation> + </message> + <message> + <source>transaction: missing callback</source> + <translation>تراکنش: callback یافت نشد</translation> + </message> + <message> + <source>SQL: database version mismatch</source> + <translation>SQL: عدم تطابق نسخه پایگاه داده</translation> + </message> +</context> +<context> + <name>QDeclarativeFlipable</name> + <message> + <source>front is a write-once property</source> + <translation>front یک ویژگی یک بار نوشتنی است</translation> + </message> + <message> + <source>back is a write-once property</source> + <translation>back یک ویژگی یک بار نوشتنی است</translation> + </message> +</context> +<context> + <name>QDeclarativeImportDatabase</name> + <message> + <source>cannot load module "%1": File name case mismatch for "%2"</source> + <translation>نمیتوان ماژول «%1» را بارگذاری کرد: مورد نام پرونده با «%2» تطابق ندارد</translation> + </message> + <message> + <source>module "%1" definition "%2" not readable</source> + <translation>تعریف «%2» ماژول «%1» قابل خواندن نیست</translation> + </message> + <message> + <source>plugin cannot be loaded for module "%1": %2</source> + <translation>افزونه نمیتواند برای ماژول «%1» بارگذاری شود: %2</translation> + </message> + <message> + <source>module "%1" plugin "%2" not found</source> + <translation>افزونه «%2» ماژول «%1» پیدا نشد</translation> + </message> + <message> + <source>module "%1" version %2.%3 is not installed</source> + <translation>ماژول «%1» نسخه %2 %3 نصب نشده است</translation> + </message> + <message> + <source>module "%1" is not installed</source> + <translation>ماژول «%1» نصب نشده است</translation> + </message> + <message> + <source>"%1": no such directory</source> + <translation>«%1»: چنین پوشهای وجود ندارد</translation> + </message> + <message> + <source>import "%1" has no qmldir and no namespace</source> + <translation>در «%1» هیچ qmldir و فضای نامی وجود ندارد</translation> + </message> + <message> + <source>- %1 is not a namespace</source> + <translation>- %1 یک فضاینام نیست</translation> + </message> + <message> + <source>- nested namespaces not allowed</source> + <translation>- فضای نام تودرتو مجاز نیست</translation> + </message> + <message> + <source>local directory</source> + <translation>پوشه محلی</translation> + </message> + <message> + <source>is ambiguous. Found in %1 and in %2</source> + <translation>مبهم است. در %1 و %2 پیدا شد</translation> + </message> + <message> + <source>is ambiguous. Found in %1 in version %2.%3 and %4.%5</source> + <translation>مبهم است. در %1 در نسخه %2 %3 و %4 %5 پیدا شد</translation> + </message> + <message> + <source>is instantiated recursively</source> + <translation>به صورت بازگشتی معرفی شده است</translation> + </message> + <message> + <source>is not a type</source> + <translation>یک نوع نیست</translation> + </message> + <message> + <source>File name case mismatch for "%2"</source> + <translation>عدم تطابق حالت نام پرونده با «%2»</translation> + </message> +</context> +<context> + <name>QDeclarativeKeyNavigationAttached</name> + <message> + <source>KeyNavigation is only available via attached properties</source> + <translation>KeyNavigation فقط از طریق ویژگیهای ضمیمه شده موجود است</translation> + </message> +</context> +<context> + <name>QDeclarativeKeysAttached</name> + <message> + <source>Keys is only available via attached properties</source> + <translation>کلیدها فقط از طریق ویژگیهای وابسته در دسترس هستند</translation> + </message> +</context> +<context> + <name>QDeclarativeLayoutMirroringAttached</name> + <message> + <source>LayoutDirection attached property only works with Items</source> + <translation>ویژگی ضمیمهشده LayoutDirection تنها با Item ها کار میکند</translation> + </message> + <message> + <source>LayoutMirroring is only available via attached properties</source> + <translation>LayoutMirroring تنها بههمراه ویژگیهای ضمیمهشده موجود است</translation> + </message> +</context> +<context> + <name>QDeclarativeListModel</name> + <message> + <source>remove: index %1 out of range</source> + <translation>remove: شاخص %1 خارج از دامنه است</translation> + </message> + <message> + <source>insert: value is not an object</source> + <translation>insert: مقدار ، یک شی نیست</translation> + </message> + <message> + <source>insert: index %1 out of range</source> + <translation>insert: شاخص %1 خارج از دامنه است</translation> + </message> + <message> + <source>move: out of range</source> + <translation>move: خارج از دامنه</translation> + </message> + <message> + <source>append: value is not an object</source> + <translation>append: مقدار ، یک شی نیست</translation> + </message> + <message> + <source>set: value is not an object</source> + <translation>set: مقدار ، یک شی نیست</translation> + </message> + <message> + <source>set: index %1 out of range</source> + <translation>set: شاخص %1 خارج از دامنه است</translation> + </message> + <message> + <source>ListElement: cannot contain nested elements</source> + <translation>ListElement: نمیتواند دربردارنده عناصر تودرتو باشد</translation> + </message> + <message> + <source>ListElement: cannot use reserved "id" property</source> + <translation>ListElement: نمیتواند از ویژگی رزرو شده «id» استفاده کند</translation> + </message> + <message> + <source>ListElement: cannot use script for property value</source> + <translation>ListElement: نمیتوان از اسکریپت برای ویژگی مقدار استفاده کرد</translation> + </message> + <message> + <source>ListModel: undefined property '%1'</source> + <translation>ListElement: ویژگی «%1» تعریف نشده است</translation> + </message> +</context> +<context> + <name>QDeclarativeLoader</name> + <message> + <source>Loader does not support loading non-visual elements.</source> + <translation>بارکننده بار کردن عناصر غیربصری را پشتیبانی نمیکند.</translation> + </message> +</context> +<context> + <name>QDeclarativeParentAnimation</name> + <message> + <source>Unable to preserve appearance under complex transform</source> + <translation>نمیتوان ظاهر را تحت تبدیل پیچیده حفظ کرد</translation> + </message> + <message> + <source>Unable to preserve appearance under non-uniform scale</source> + <translation>نمیتوان ظاهر را تحت مقیاس غیر یکنواخت حفظ کرد</translation> + </message> + <message> + <source>Unable to preserve appearance under scale of 0</source> + <translation>نمیتوان ظاهر را تحت مقیاس صفر حفظ کرد</translation> + </message> +</context> +<context> + <name>QDeclarativeParentChange</name> + <message> + <source>Unable to preserve appearance under complex transform</source> + <translation>نمیتوان ظاهر را تحت تبدیل پیچیده حفظ کرد</translation> + </message> + <message> + <source>Unable to preserve appearance under non-uniform scale</source> + <translation>نمیتوان ظاهر را تحت مقیاس غیر یکنواخت حفظ کرد</translation> + </message> + <message> + <source>Unable to preserve appearance under scale of 0</source> + <translation>نمیتوان ظاهر را تحت مقیاس صفر حفظ کرد</translation> + </message> +</context> +<context> + <name>QDeclarativeParser</name> + <message> + <source>Illegal unicode escape sequence</source> + <translation>دنباله فرار یونیکد غیرمجاز</translation> + </message> + <message> + <source>Illegal character</source> + <translation>نویسه غیرمجاز</translation> + </message> + <message> + <source>Unclosed string at end of line</source> + <translation>رشته بسته نشده در انتهای خط</translation> + </message> + <message> + <source>Illegal escape sequence</source> + <translation>دنباله فرار غیر مجاز</translation> + </message> + <message> + <source>Unclosed comment at end of file</source> + <translation>توضیح بسته نشده در انتهای خط</translation> + </message> + <message> + <source>Illegal syntax for exponential number</source> + <translation>ترکیب غیرمجاز برای اعداد نمایی</translation> + </message> + <message> + <source>Identifier cannot start with numeric literal</source> + <translation>شناسه نمیتواند با عدد شروع شود</translation> + </message> + <message> + <source>Unterminated regular expression literal</source> + <translation>عبارت منظم پایان نیافته</translation> + </message> + <message> + <source>Invalid regular expression flag '%0'</source> + <translation>پرچم غیر مجاز عبارت منظم «%0»</translation> + </message> + <message> + <source>Unterminated regular expression backslash sequence</source> + <translation>دنباله backslash پایان نیافته عبارت منظم</translation> + </message> + <message> + <source>Unterminated regular expression class</source> + <translation>کلاس عبارت منظم پایان نیافته</translation> + </message> + <message> + <source>Syntax error</source> + <translation>خطای نحوی</translation> + </message> + <message> + <source>Unexpected token `%1'</source> + <translation>نشانه غیر منتظره «%1»</translation> + </message> + <message> + <source>Expected token `%1'</source> + <translation>نشانه مورد انتظار «%1»</translation> + </message> + <message> + <source>Property value set multiple times</source> + <translation>مقدار ویژگی چند بار تعیین شد</translation> + </message> + <message> + <source>Expected type name</source> + <translation>نام نوع مورد انتظار</translation> + </message> + <message> + <source>Invalid import qualifier ID</source> + <translation>شناسه نامعتبر توصیف کننده import</translation> + </message> + <message> + <source>Reserved name "Qt" cannot be used as an qualifier</source> + <translation>نام رزرو شده «Qt» نمیتواند به عنوان توصیفکننده مورد استفاده قرار گیرد</translation> + </message> + <message> + <source>Script import qualifiers must be unique.</source> + <translation>توصیفکننده وارد کردن اسکریپت باید یکتا باشد.</translation> + </message> + <message> + <source>Script import requires a qualifier</source> + <translation>وارد کردن اسکریپت یک توصیفکننده نیاز دارد</translation> + </message> + <message> + <source>Library import requires a version</source> + <translation>وارد کردن کتابخانه یک نسخه نیاز دارد</translation> + </message> + <message> + <source>Expected parameter type</source> + <translation>نوع پارامتر مورد انتظار</translation> + </message> + <message> + <source>Invalid property type modifier</source> + <translation>تغییردهنده غیرمجاز نوع ویژگی</translation> + </message> + <message> + <source>Unexpected property type modifier</source> + <translation>تغییردهنده غیرمنتظره نوع ویژگی</translation> + </message> + <message> + <source>Expected property type</source> + <translation>نوع ویژگی مورد انتظار</translation> + </message> + <message> + <source>Readonly not yet supported</source> + <translation>فقطخواندنی هنوز پشتیبانی نمیشود</translation> + </message> + <message> + <source>JavaScript declaration outside Script element</source> + <translation>اعلان JavaScript خارج از عنصر Script</translation> + </message> +</context> +<context> + <name>QDeclarativePauseAnimation</name> + <message> + <source>Cannot set a duration of < 0</source> + <translation>نمیتوان مدت زمان را کمتر از صفر قرار داد</translation> + </message> +</context> +<context> + <name>QDeclarativePixmap</name> + <message> + <source>Error decoding: %1: %2</source> + <translation>خطای رمزگشایی: %1: %2</translation> + </message> + <message> + <source>Failed to get image from provider: %1</source> + <translation>بازیابی ناموفق تصویر از سرویسدهنده: %1</translation> + </message> + <message> + <source>Cannot open: %1</source> + <translation>نمیتوان باز کرد: %1</translation> + </message> +</context> +<context> + <name>QDeclarativePropertyAnimation</name> + <message> + <source>Cannot set a duration of < 0</source> + <translation>نمیتوان مدت زمان را کمتر از صفر قرار داد</translation> + </message> +</context> +<context> + <name>QDeclarativePropertyChanges</name> + <message> + <source>PropertyChanges does not support creating state-specific objects.</source> + <translation>propertyChanges ایجاد اشیاء state-specific را پشتیبانی نمیکند.</translation> + </message> + <message> + <source>Cannot assign to non-existent property "%1"</source> + <translation>نمیتوان به ویژگی ناموجود «%1» اختصاص داد</translation> + </message> + <message> + <source>Cannot assign to read-only property "%1"</source> + <translation>نمیتوان به ویژگی فقط خواندنی «%1» اختصاص داد</translation> + </message> +</context> +<context> + <name>QDeclarativeTextInput</name> + <message> + <source>Could not load cursor delegate</source> + <translation>نمیتوان نماینده نشانگر را بارگذاری کرد</translation> + </message> + <message> + <source>Could not instantiate cursor delegate</source> + <translation>نمیتوان نماینده نشانگر را معرفی کرد</translation> + </message> +</context> +<context> + <name>QDeclarativeTypeLoader</name> + <message> + <source>Script %1 unavailable</source> + <translation>اسکریپت %1 در دسترس نیست</translation> + </message> + <message> + <source>Type %1 unavailable</source> + <translation>نوع %1 در دسترس نیست</translation> + </message> + <message> + <source>Namespace %1 cannot be used as a type</source> + <translation>فضای نام %1 نمیتواند به عنوان نوع استفاده شود</translation> + </message> + <message> + <source>%1 %2</source> + <translation>%1 %2</translation> + </message> +</context> +<context> + <name>QDeclarativeVME</name> + <message> + <source>Unable to create object of type %1</source> + <translation>نمیتوان شیء نوع %1 را ایجاد کرد</translation> + </message> + <message> + <source>Cannot assign value %1 to property %2</source> + <translation>نمیتوان مقدار %1 را به ویژگی %2 اختصاص داد</translation> + </message> + <message> + <source>Cannot assign object type %1 with no default method</source> + <translation>.نمیتوان شیء نوع %1 را بدون متد پیشفرض تعیین کرد</translation> + </message> + <message> + <source>Cannot connect mismatched signal/slot %1 %vs. %2</source> + <translation>نمیتوان سیگنال/اسلات نامناسب %1 / %2 را به هم متصل کرد</translation> + </message> + <message> + <source>Cannot assign an object to signal property %1</source> + <translation>نمیتوان یک شیء را به ویژگی سیگنال %1 اختصاص داد</translation> + </message> + <message> + <source>Cannot assign object to list</source> + <translation>نمیتوان شیء را به لیست اختصاص داد</translation> + </message> + <message> + <source>Cannot assign object to interface property</source> + <translation>نمیتوان شیء را به ویژگی interface اختصاص داد</translation> + </message> + <message> + <source>Unable to create attached object</source> + <translation>نمیتوان شیء وابسته ایجاد کرد</translation> + </message> + <message> + <source>Cannot set properties on %1 as it is null</source> + <translation>نمیتوان ویژگیها را روی %1 تنظیم کرد چون که تهی است</translation> + </message> +</context> +<context> + <name>QDeclarativeVisualDataModel</name> + <message> + <source>Delegate component must be Item type.</source> + <translation>جزء نماینده باید یک نوع آیتم باشد.</translation> + </message> +</context> +<context> + <name>QDeclarativeXmlListModel</name> + <message> + <source>Qt was built without support for xmlpatterns</source> + <translation>Qt بدون پشتیبانی از xmlpatterns ساخته شده است</translation> + </message> +</context> +<context> + <name>QDeclarativeXmlListModelRole</name> + <message> + <source>An XmlRole query must not start with '/'</source> + <translation>یک .پرسوجوی XmlRole نباید با «/» شروع شود</translation> + </message> +</context> +<context> + <name>QDeclarativeXmlRoleList</name> + <message> + <source>An XmlListModel query must start with '/' or "//"</source> + <translation>یک پرس و جوی XmlListModel باید با «/» یا «//» شروع شود</translation> + </message> +</context> +<context> + <name>QDial</name> + <message> + <source>QDial</source> + <translation>کلاس QDial</translation> + </message> + <message> + <source>SpeedoMeter</source> + <translation>سرعتسنج</translation> + </message> + <message> + <source>SliderHandle</source> + <translation>دستهلغزنده</translation> + </message> +</context> +<context> + <name>QDialog</name> + <message> + <source>Done</source> + <translation>انجام شد</translation> + </message> + <message> + <source>What's This?</source> + <translation>این چیست؟</translation> + </message> +</context> +<context> + <name>QDialogButtonBox</name> + <message> + <source>OK</source> + <translation>تأیید</translation> + </message> + <message> + <source>&OK</source> + <translation>&تأیید</translation> + </message> + <message> + <source>&Save</source> + <translation>&ذخیره</translation> + </message> + <message> + <source>Save</source> + <translation>ذخیره</translation> + </message> + <message> + <source>Open</source> + <translation>باز کردن</translation> + </message> + <message> + <source>&Cancel</source> + <translation>&لغو</translation> + </message> + <message> + <source>Cancel</source> + <translation>لغو</translation> + </message> + <message> + <source>&Close</source> + <translation>&بستن</translation> + </message> + <message> + <source>Close</source> + <translation>بستن</translation> + </message> + <message> + <source>Apply</source> + <translation>اعمال کردن</translation> + </message> + <message> + <source>Reset</source> + <translation>بازتنظیم</translation> + </message> + <message> + <source>Help</source> + <translation>کمک</translation> + </message> + <message> + <source>Don't Save</source> + <translation>ذخیره نکن</translation> + </message> + <message> + <source>Close without Saving</source> + <translation>بستن بدون ذخیره</translation> + </message> + <message> + <source>Discard</source> + <translation>دورانداختن</translation> + </message> + <message> + <source>&Yes</source> + <translation>&بله</translation> + </message> + <message> + <source>Yes to &All</source> + <translation>&بله برای همه</translation> + </message> + <message> + <source>&No</source> + <translation>&نه</translation> + </message> + <message> + <source>N&o to All</source> + <translation>ن&ه برای همه</translation> + </message> + <message> + <source>Save All</source> + <translation>ذخیره همه</translation> + </message> + <message> + <source>Abort</source> + <translation>لغو کردن</translation> + </message> + <message> + <source>Retry</source> + <translation>تلاش دوباره</translation> + </message> + <message> + <source>Ignore</source> + <translation>نادیدهگرفتن</translation> + </message> + <message> + <source>Restore Defaults</source> + <translation>بازنشانی پیشفرضها</translation> + </message> +</context> +<context> + <name>QDirModel</name> + <message> + <source>Name</source> + <translation>نام</translation> + </message> + <message> + <source>Size</source> + <translation>حجم</translation> + </message> + <message> + <source>Kind</source> + <comment>Match OS X Finder</comment> + <translation>نوع</translation> + </message> + <message> + <source>Type</source> + <comment>All other platforms</comment> + <translation>نوع</translation> + </message> + <message> + <source>Date Modified</source> + <translation>تاریخ تغییر</translation> + </message> +</context> +<context> + <name>QDockWidget</name> + <message> + <source>Close</source> + <translation>بستن</translation> + </message> + <message> + <source>Dock</source> + <translation>ثابت</translation> + </message> + <message> + <source>Float</source> + <translation>شناور</translation> + </message> +</context> +<context> + <name>QDoubleSpinBox</name> + <message> + <source>More</source> + <translation>بیشتر</translation> + </message> + <message> + <source>Less</source> + <translation>کمتر</translation> + </message> +</context> +<context> + <name>QErrorMessage</name> + <message> + <source>Debug Message:</source> + <translation>پیغام اشکالزدایی:</translation> + </message> + <message> + <source>Warning:</source> + <translation>هشدار:</translation> + </message> + <message> + <source>Fatal Error:</source> + <translation>خطای مهلک:</translation> + </message> + <message> + <source>&Show this message again</source> + <translation>این پیغام را &دوباره نمایش بده</translation> + </message> + <message> + <source>&OK</source> + <translation>&تأیید</translation> + </message> +</context> +<context> + <name>QFile</name> + <message> + <source>Destination file exists</source> + <translation>پرونده مقصد موجود است</translation> + </message> + <message> + <source>Will not rename sequential file using block copy</source> + <translation>پرونده ترتیبی با استفاده از کپی بلاکها تغییر نام داده نخواهد شد</translation> + </message> + <message> + <source>Cannot remove source file</source> + <translation>نمیتوان پرونده منبع را حذف کرد</translation> + </message> + <message> + <source>Cannot open %1 for input</source> + <translation>نمیتوان %1 را بهعنوان ورودی باز کرد</translation> + </message> + <message> + <source>Cannot open for output</source> + <translation>نمیتوان برای خروجی باز کرد</translation> + </message> + <message> + <source>Failure to write block</source> + <translation>نگارش ناموفق بلاک</translation> + </message> + <message> + <source>Cannot create %1 for output</source> + <translation>نمیتوان %1 را برای خروجی باز کرد</translation> + </message> +</context> +<context> + <name>QFileDialog</name> + <message> + <source>Look in:</source> + <translation>جستجو در:</translation> + </message> + <message> + <source>Back</source> + <translation>عقب</translation> + </message> + <message> + <source>Go back</source> + <translation>عقبگرد</translation> + </message> + <message> + <source>Forward</source> + <translation>جلوتر</translation> + </message> + <message> + <source>Go forward</source> + <translation>جلوگرد</translation> + </message> + <message> + <source>Parent Directory</source> + <translation>پوشه بالاتر</translation> + </message> + <message> + <source>Go to the parent directory</source> + <translation>برو به پوشه بالاتر</translation> + </message> + <message> + <source>Create New Folder</source> + <translation>ایجاد پوشه جدید</translation> + </message> + <message> + <source>Create a New Folder</source> + <translation>ایجاد یک پوشه جدید</translation> + </message> + <message> + <source>List View</source> + <translation>نمایش سیاهه</translation> + </message> + <message> + <source>Change to list view mode</source> + <translation>تغییر به حالت نمایش سیاهه</translation> + </message> + <message> + <source>Detail View</source> + <translation>نمایش با جزئیات</translation> + </message> + <message> + <source>Change to detail view mode</source> + <translation>تغییر به حالت نمایش با جزئیات</translation> + </message> + <message> + <source>Files of type:</source> + <translation>پروندههایی از نوع:</translation> + </message> + <message> + <source>Find Directory</source> + <translation>یافتن پوشه</translation> + </message> + <message> + <source>Open</source> + <translation>بازکردن</translation> + </message> + <message> + <source>Save As</source> + <translation>ذخیره به عنوان</translation> + </message> + <message> + <source>All Files (*)</source> + <translation>تمام پروندهها (*)</translation> + </message> + <message> + <source>Show </source> + <translation>نمایش</translation> + </message> + <message> + <source>&Rename</source> + <translation>&تغییر نام</translation> + </message> + <message> + <source>&Delete</source> + <translation>&حذف</translation> + </message> + <message> + <source>Show &hidden files</source> + <translation>نمایش پروندههای م&خفی</translation> + </message> + <message> + <source>&New Folder</source> + <translation>&پوشه جدید</translation> + </message> + <message> + <source>Directory:</source> + <translation>پوشه:</translation> + </message> + <message> + <source>File &name:</source> + <translation>&نام پرونده:</translation> + </message> + <message> + <source>&Open</source> + <translation>&بازکردن</translation> + </message> + <message> + <source>&Save</source> + <translation>&ذخیره</translation> + </message> + <message> + <source>Directories</source> + <translation>پوشهها</translation> + </message> + <message> + <source>&Choose</source> + <translation>&انتخاب</translation> + </message> + <message> + <source>%1 +Directory not found. +Please verify the correct directory name was given.</source> + <translation>%1 +پوشه یافت نشد +لطفا بررسی کنید که نام مسیر بهدرستی داده شده باشد.</translation> + </message> + <message> + <source>%1 already exists. +Do you want to replace it?</source> + <translation>%1 از قبل موجود است. +آیا مایل هستید جایگزین شود؟</translation> + </message> + <message> + <source>%1 +File not found. +Please verify the correct file name was given.</source> + <translation>%1 +پرونده یافت نشد. +لطفا درستی نام پرونده داده شده را بررسی کنید.</translation> + </message> + <message> + <source>New Folder</source> + <translation>پوشه جدید</translation> + </message> + <message> + <source>'%1' is write protected. +Do you want to delete it anyway?</source> + <translation>'%1' از حفاظت نوشتاری برخوردار است. +با این حال آیا مایل هستید حذف شود؟</translation> + </message> + <message> + <source>Are sure you want to delete '%1'?</source> + <translation>آیا مطمئن هستید میخواهید %1 را حذف کنید؟</translation> + </message> + <message> + <source>Could not delete directory.</source> + <translation>نمیتوان پوشه را حذف کرد.</translation> + </message> + <message> + <source>Recent Places</source> + <translation>مکانهای اخیر</translation> + </message> + <message> + <source>All Files (*.*)</source> + <translation>تمام پروندهها (*.*)</translation> + </message> + <message> + <source>Remove</source> + <translation>حذف</translation> + </message> + <message> + <source>My Computer</source> + <translation>رایانه من</translation> + </message> + <message> + <source>Drive</source> + <translation>درایو</translation> + </message> + <message> + <source>File</source> + <translation>پرونده</translation> + </message> + <message> + <source>File Folder</source> + <comment>Match Windows Explorer</comment> + <translation>پوشه پرونده</translation> + </message> + <message> + <source>Folder</source> + <comment>All other platforms</comment> + <translation>پوشه</translation> + </message> + <message> + <source>Alias</source> + <comment>Mac OS X Finder</comment> + <translation>نام مستعار</translation> + </message> + <message> + <source>Shortcut</source> + <comment>All other platforms</comment> + <translation>میانبر</translation> + </message> + <message> + <source>Unknown</source> + <translation>ناشناخته</translation> + </message> +</context> +<context> + <name>QFileSystemModel</name> + <message> + <source>%1 TB</source> + <translation>%1 ترابایت</translation> + </message> + <message> + <source>%1 GB</source> + <translation>%1 گیگابایت</translation> + </message> + <message> + <source>%1 MB</source> + <translation>%1 مگابایت</translation> + </message> + <message> + <source>%1 KB</source> + <translation>%1 کیلوبایت</translation> + </message> + <message> + <source>%1 bytes</source> + <translation>%1 بایت</translation> + </message> + <message> + <source>Invalid filename</source> + <translation>نام نامعتبر پرونده</translation> + </message> + <message> + <source><b>The name "%1" can not be used.</b><p>Try using another name, with fewer characters or no punctuations marks.</source> + <translation><b>نام "%1" نمیتواند مورد استفاده قرار گیرد.</b><p>نام دیگری با تعداد نویسههای کمتر یا نامی بدون علایم نگارشی را امتحان کنید.</translation> + </message> + <message> + <source>Name</source> + <translation>نام</translation> + </message> + <message> + <source>Size</source> + <translation>حجم</translation> + </message> + <message> + <source>Kind</source> + <comment>Match OS X Finder</comment> + <translation>نوع</translation> + </message> + <message> + <source>Type</source> + <comment>All other platforms</comment> + <translation>نوع</translation> + </message> + <message> + <source>Date Modified</source> + <translation>تاریخ تغییر</translation> + </message> + <message> + <source>My Computer</source> + <translation>رایانه من</translation> + </message> + <message> + <source>Computer</source> + <translation>رایانه</translation> + </message> + <message> + <source>%1 byte(s)</source> + <translation>%1 بایت</translation> + </message> +</context> +<context> + <name>QFontDatabase</name> + <message> + <source>Normal</source> + <translation>عادی</translation> + </message> + <message> + <source>Bold</source> + <translation>توپر</translation> + </message> + <message> + <source>Demi Bold</source> + <translation>نیمهتوپر</translation> + </message> + <message> + <source>Black</source> + <translation>سیاه</translation> + </message> + <message> + <source>Demi</source> + <translation>نیمه</translation> + </message> + <message> + <source>Light</source> + <translation>سبک</translation> + </message> + <message> + <source>Italic</source> + <translation>کج</translation> + </message> + <message> + <source>Oblique</source> + <translation>اریب</translation> + </message> + <message> + <source>Any</source> + <translation>همه</translation> + </message> + <message> + <source>Latin</source> + <translation>لاتین</translation> + </message> + <message> + <source>Greek</source> + <translation>یونانی</translation> + </message> + <message> + <source>Cyrillic</source> + <translation>سیریلیک</translation> + </message> + <message> + <source>Armenian</source> + <translation>ارمنی</translation> + </message> + <message> + <source>Hebrew</source> + <translation>عبرانی</translation> + </message> + <message> + <source>Arabic</source> + <translation>عربی</translation> + </message> + <message> + <source>Syriac</source> + <translation>سریانی</translation> + </message> + <message> + <source>Thaana</source> + <translation>سانا</translation> + </message> + <message> + <source>Devanagari</source> + <translation>دوناگاری</translation> + </message> + <message> + <source>Bengali</source> + <translation>بنگالی</translation> + </message> + <message> + <source>Gurmukhi</source> + <translation>گورموخی</translation> + </message> + <message> + <source>Gujarati</source> + <translation>گوجارتی</translation> + </message> + <message> + <source>Oriya</source> + <translation>اوریا</translation> + </message> + <message> + <source>Tamil</source> + <translation>تامیل</translation> + </message> + <message> + <source>Telugu</source> + <translation>تلوگو</translation> + </message> + <message> + <source>Kannada</source> + <translation>کانادا</translation> + </message> + <message> + <source>Malayalam</source> + <translation>مالایی</translation> + </message> + <message> + <source>Sinhala</source> + <translation>سینهالا</translation> + </message> + <message> + <source>Thai</source> + <translation>تایلندی</translation> + </message> + <message> + <source>Lao</source> + <translation>لائوسی</translation> + </message> + <message> + <source>Tibetan</source> + <translation>تبتی</translation> + </message> + <message> + <source>Myanmar</source> + <translation>میانماری</translation> + </message> + <message> + <source>Georgian</source> + <translation>گرجی</translation> + </message> + <message> + <source>Khmer</source> + <translation>خیمر</translation> + </message> + <message> + <source>Simplified Chinese</source> + <translation>چینی ساده شده</translation> + </message> + <message> + <source>Traditional Chinese</source> + <translation>چینی تجاری</translation> + </message> + <message> + <source>Japanese</source> + <translation>ژاپنی</translation> + </message> + <message> + <source>Korean</source> + <translation>کرهای</translation> + </message> + <message> + <source>Vietnamese</source> + <translation>ویتنامی</translation> + </message> + <message> + <source>Symbol</source> + <translation>نشانه</translation> + </message> + <message> + <source>Ogham</source> + <translation>اوغام</translation> + </message> + <message> + <source>Runic</source> + <translation>رمزی</translation> + </message> + <message> + <source>N'Ko</source> + <translation>انکو</translation> + </message> +</context> +<context> + <name>QFontDialog</name> + <message> + <source>Select Font</source> + <translation>انتخاب فونت</translation> + </message> + <message> + <source>&Font</source> + <translation>&فونت</translation> + </message> + <message> + <source>Font st&yle</source> + <translation>&سبک فونت</translation> + </message> + <message> + <source>&Size</source> + <translation>&اندازه</translation> + </message> + <message> + <source>Effects</source> + <translation>جلوهها</translation> + </message> + <message> + <source>Stri&keout</source> + <translation>&خطزده</translation> + </message> + <message> + <source>&Underline</source> + <translation>&زیرخطدار</translation> + </message> + <message> + <source>Sample</source> + <translation>نمونه</translation> + </message> + <message> + <source>Wr&iting System</source> + <translation>سامانه &نوشتاری</translation> + </message> +</context> +<context> + <name>QFtp</name> + <message> + <source>Not connected</source> + <translation>متصل نمیباشد</translation> + </message> + <message> + <source>Host %1 not found</source> + <translation>میزبان %1 پیدا نشد</translation> + </message> + <message> + <source>Connection refused to host %1</source> + <translation>اتصال به میزبان %1 رد شد</translation> + </message> + <message> + <source>Connection timed out to host %1</source> + <translation>زمان اتصال به میزبان %1 به پایان رسید</translation> + </message> + <message> + <source>Connected to host %1</source> + <translation>اتصال به میزبان %1 برقرار شد</translation> + </message> + <message> + <source>Connection refused for data connection</source> + <translation>اتصال برقراری اتصال داده را رد کرد</translation> + </message> + <message> + <source>Unknown error</source> + <translation>خطای ناشناخته</translation> + </message> + <message> + <source>Connecting to host failed: +%1</source> + <translation>اتصال ناموفق به میزبان: +%1</translation> + </message> + <message> + <source>Login failed: +%1</source> + <translation>ورود ناموفق: +%1</translation> + </message> + <message> + <source>Listing directory failed: +%1</source> + <translation>لیست کردن پوشه شکست خورد: +%1</translation> + </message> + <message> + <source>Changing directory failed: +%1</source> + <translation>تغییر پوشه انجام نشد: +%1</translation> + </message> + <message> + <source>Downloading file failed: +%1</source> + <translation>دانلود ناموفق پرونده: +%1</translation> + </message> + <message> + <source>Uploading file failed: +%1</source> + <translation>آپلود ناموفق پرونده: +%1</translation> + </message> + <message> + <source>Removing file failed: +%1</source> + <translation>حذف ناموفق پرونده: +%1</translation> + </message> + <message> + <source>Creating directory failed: +%1</source> + <translation>ایجاد پوشه انجام نشد: +%1</translation> + </message> + <message> + <source>Removing directory failed: +%1</source> + <translation>حدف پوشه انجام نشد: +%1</translation> + </message> + <message> + <source>Connection closed</source> + <translation>اتصال بسته شد</translation> + </message> + <message> + <source>Host %1 found</source> + <translation>میزبان پیدا %1 شد</translation> + </message> + <message> + <source>Connection to %1 closed</source> + <translation>اتصال به %1 بسته شد</translation> + </message> + <message> + <source>Host found</source> + <translation>میزبان پیدا شد</translation> + </message> + <message> + <source>Connected to host</source> + <translation>اتصال به میزبان برقرار شد</translation> + </message> +</context> +<context> + <name>QHostInfo</name> + <message> + <source>No host name given</source> + <translation>نام میزبان داده نشده است</translation> + </message> + <message> + <source>Unknown error</source> + <translation>خطای ناشناخته</translation> + </message> +</context> +<context> + <name>QHostInfoAgent</name> + <message> + <source>No host name given</source> + <translation>نام میزبان داده نشده است</translation> + </message> + <message> + <source>Invalid hostname</source> + <translation>نام نامعتبر میزبان</translation> + </message> + <message> + <source>Unknown address type</source> + <translation>نوع ناشناخته آدرس</translation> + </message> + <message> + <source>Host not found</source> + <translation>میزبان پیدا نشد</translation> + </message> + <message> + <source>Unknown error</source> + <translation>خطای ناشناخته</translation> + </message> +</context> +<context> + <name>QHttp</name> + <message> + <source>HTTPS connection requested but SSL support not compiled in</source> + <translation>اتصال HTTPS در خواست شد اما پشتیبانی SSL گردآوری نشد</translation> + </message> + <message> + <source>Unknown error</source> + <translation>خطای ناشناخته</translation> + </message> + <message> + <source>Request aborted</source> + <translation>درخواست لغو شد</translation> + </message> + <message> + <source>No server set to connect to</source> + <translation>سرویسدهندهای برای اتصال تعیین نشده است</translation> + </message> + <message> + <source>Wrong content length</source> + <translation>طول اشتباه برای محتوا</translation> + </message> + <message> + <source>Server closed connection unexpectedly</source> + <translation>بسته شدن غیرمنتظره اتصال از سمت سرویسدهنده</translation> + </message> + <message> + <source>Connection refused (or timed out)</source> + <translation>اتصال رد شد (یا فرصت به اتمام رسید)</translation> + </message> + <message> + <source>Host %1 not found</source> + <translation>میزبان %1 پیدا نشد</translation> + </message> + <message> + <source>HTTP request failed</source> + <translation>درخواست HTTP انجام نشد</translation> + </message> + <message> + <source>Invalid HTTP response header</source> + <translation>سرآیند نامعتبر پاسخ HTTP</translation> + </message> + <message> + <source>Unknown authentication method</source> + <translation>روش اعتبارسنجی ناشناخته</translation> + </message> + <message> + <source>Proxy authentication required</source> + <translation>اعتبارسنجی پروکسی نیاز است</translation> + </message> + <message> + <source>Authentication required</source> + <translation>اعتبارسنجی نیاز است</translation> + </message> + <message> + <source>Invalid HTTP chunked body</source> + <translation>بدنه قطعهبندی شده نامعتبر HTTP</translation> + </message> + <message> + <source>Error writing response to device</source> + <translation>خطای نوشتن پاسخ روی دستگاه</translation> + </message> + <message> + <source>Connection refused</source> + <translation>اتصال رد شد</translation> + </message> + <message> + <source>Connection closed</source> + <translation>اتصال بسته شد</translation> + </message> + <message> + <source>Proxy requires authentication</source> + <translation>پروکسی به اعتبار سنجی نیاز دارد</translation> + </message> + <message> + <source>Host requires authentication</source> + <translation>میزبان به اعتبار سنجی نیاز دارد</translation> + </message> + <message> + <source>Data corrupted</source> + <translation>داده خراب است</translation> + </message> + <message> + <source>Unknown protocol specified</source> + <translation>پروتکل ناشناخته تعیین شده است</translation> + </message> + <message> + <source>SSL handshake failed</source> + <translation>دستدهی ناموفق SSL</translation> + </message> + <message> + <source>Host %1 found</source> + <translation>میزبان %1 پیدا شد</translation> + </message> + <message> + <source>Connected to host %1</source> + <translation>اتصال به میزبان %1 برقرار شد</translation> + </message> + <message> + <source>Connection to %1 closed</source> + <translation>اتصال به %1 بسته شد</translation> + </message> + <message> + <source>Host found</source> + <translation>میزبان پیدا شد</translation> + </message> + <message> + <source>Connected to host</source> + <translation>اتصال به میزبان برقرار شد</translation> + </message> +</context> +<context> + <name>QHttpSocketEngine</name> + <message> + <source>Did not receive HTTP response from proxy</source> + <translation>پاسخ HTTP از پروکسی دریافت نشد</translation> + </message> + <message> + <source>Error parsing authentication request from proxy</source> + <translation>درخواست خطای تجزیه اعتبارسنجی از پروکسی</translation> + </message> + <message> + <source>Authentication required</source> + <translation>اعتبارسنجی نیاز است</translation> + </message> + <message> + <source>Proxy denied connection</source> + <translation>پروکسی اتصال را رد کرد</translation> + </message> + <message> + <source>Error communicating with HTTP proxy</source> + <translation>خطای ارتباط با پروکسی HTTP</translation> + </message> + <message> + <source>Proxy server not found</source> + <translation>سرویسدهنده پروکسی پیدا نشد</translation> + </message> + <message> + <source>Proxy connection refused</source> + <translation>اتصال پروکسی رد شد</translation> + </message> + <message> + <source>Proxy server connection timed out</source> + <translation>زمان اتصال به سرویس دهنده پروکسی تمام شد</translation> + </message> + <message> + <source>Proxy connection closed prematurely</source> + <translation>اتصال پروکسی نابهنگام بسته شد</translation> + </message> +</context> +<context> + <name>QIBaseDriver</name> + <message> + <source>Error opening database</source> + <translation>خطا در باز کردن پایگاه داده</translation> + </message> + <message> + <source>Could not start transaction</source> + <translation>نمیتوان تراکنش را شروع کرد</translation> + </message> + <message> + <source>Unable to commit transaction</source> + <translation>نمیتوان تراکنش را ارسال کرد</translation> + </message> + <message> + <source>Unable to rollback transaction</source> + <translation>نمیتوان تراکنش را بازگرداند</translation> + </message> +</context> +<context> + <name>QIBaseResult</name> + <message> + <source>Unable to create BLOB</source> + <translation>نمیتوان BLOB را ایجاد کرد</translation> + </message> + <message> + <source>Unable to write BLOB</source> + <translation>نمیتوان در BLOB نوشت</translation> + </message> + <message> + <source>Unable to open BLOB</source> + <translation>نمیتوان BLOB را باز کرد</translation> + </message> + <message> + <source>Unable to read BLOB</source> + <translation>نمیتوان BLOB را خواند</translation> + </message> + <message> + <source>Could not find array</source> + <translation>نمیتوان آرایه را پیدا کرد</translation> + </message> + <message> + <source>Could not get array data</source> + <translation>نمیتوان دادههای آرایه را بازیابی کرد</translation> + </message> + <message> + <source>Could not get query info</source> + <translation>نمیتوان اطلاعات پرسوجو را بازیابی کرد</translation> + </message> + <message> + <source>Could not start transaction</source> + <translation>نمیتوان تراکنش را شروع کرد</translation> + </message> + <message> + <source>Unable to commit transaction</source> + <translation>نمیتوان تراکنش را ارسال کرد</translation> + </message> + <message> + <source>Could not allocate statement</source> + <translation>نمیتوان عبارت را اختصاص داد</translation> + </message> + <message> + <source>Could not prepare statement</source> + <translation>نمیتوان عبارت را آماده کرد</translation> + </message> + <message> + <source>Could not describe input statement</source> + <translation>نمیتوان عبارت ورودی را شرح داد</translation> + </message> + <message> + <source>Could not describe statement</source> + <translation>نمیتوان عبارت را شرح داد</translation> + </message> + <message> + <source>Unable to close statement</source> + <translation>نمیتوان عبارت را بست</translation> + </message> + <message> + <source>Unable to execute query</source> + <translation>نمیتوان پرسوجو را اجرا کرد</translation> + </message> + <message> + <source>Could not fetch next item</source> + <translation>نمیتوان آیتم بعدی را واکشی کرد</translation> + </message> + <message> + <source>Could not get statement info</source> + <translation>نمیتوان اطلاعات عبارت را بازیابی کرد</translation> + </message> +</context> +<context> + <name>QIODevice</name> + <message> + <source>Permission denied</source> + <translation>حق دسترسی رد شد</translation> + </message> + <message> + <source>Too many open files</source> + <translation>پروندههای زیادی باز است</translation> + </message> + <message> + <source>No such file or directory</source> + <translation>چنین پوشه یا پروندهای وجود ندارد</translation> + </message> + <message> + <source>No space left on device</source> + <translation>فضایی در دستگاه باقی نمانده است</translation> + </message> + <message> + <source>Unknown error</source> + <translation>خطای ناشناخته</translation> + </message> +</context> +<context> + <name>QInputContext</name> + <message> + <source>XIM</source> + <translation>XIM</translation> + </message> + <message> + <source>FEP</source> + <translation>FEP</translation> + </message> + <message> + <source>XIM input method</source> + <translation>روش ورودی XIM</translation> + </message> + <message> + <source>Windows input method</source> + <translation>روش ورودی ویندوز</translation> + </message> + <message> + <source>Mac OS X input method</source> + <translation>روش ورودی مکینتاش</translation> + </message> + <message> + <source>S60 FEP input method</source> + <translation>روش ورودی FEP S60</translation> + </message> +</context> +<context> + <name>QInputDialog</name> + <message> + <source>Enter a value:</source> + <translation>یک مقدار وارد کنید:</translation> + </message> +</context> +<context> + <name>QLibrary</name> + <message> + <source>Plugin verification data mismatch in '%1'</source> + <translation>داده اعتبارسنجی افزونه در «%1» تطابق ندارد</translation> + </message> + <message> + <source>The shared library was not found.</source> + <translation>کتابخانه اشتراکی پیدا نشد.</translation> + </message> + <message> + <source>The file '%1' is not a valid Qt plugin.</source> + <translation>پرونده «%1» یک افزونه معتبر Qt نیست.</translation> + </message> + <message> + <source>The plugin '%1' uses incompatible Qt library. (%2.%3.%4) [%5]</source> + <translation>افزونه «%1» از کتابخانه ناسازگار Qt استفاده میکند. (%2.%3.%4) [%5]</translation> + </message> + <message> + <source>The plugin '%1' uses incompatible Qt library. Expected build key "%2", got "%3"</source> + <translation>افزونه «%1» از کتابخانه ناسازگار Qt استفاده میکند. کلید ساخت «%2» مورد انتظار است، «%3» پیدا شد</translation> + </message> + <message> + <source>The plugin '%1' uses incompatible Qt library. (Cannot mix debug and release libraries.)</source> + <translation>افزونه «%1» از کتابخانه ناسازگار Qt استفاده میکند. (نمیتوان کتابخانههای اشکالزدایی و انتشار را ترکیب کرد.)</translation> + </message> + <message> + <source>Unknown error</source> + <translation>خطای ناشناخته</translation> + </message> + <message> + <source>Cannot load library %1: %2</source> + <translation>نمیتوان کتابخانه %1 را بارگذاری کرد: %2</translation> + </message> + <message> + <source>Cannot unload library %1: %2</source> + <translation>نمیتوان کتابخانه %1 را تخلیه کرد: %2</translation> + </message> + <message> + <source>Cannot resolve symbol "%1" in %2: %3</source> + <translation>نمیتوان درباره نماد «%1» در %2 تصمیمگیری کرد: %3</translation> + </message> +</context> +<context> + <name>QLineEdit</name> + <message> + <source>&Undo</source> + <translation>&خنثیسازی</translation> + </message> + <message> + <source>&Redo</source> + <translation>&بازانجام</translation> + </message> + <message> + <source>Cu&t</source> + <translation>ب&رش</translation> + </message> + <message> + <source>&Copy</source> + <translation>&کپی</translation> + </message> + <message> + <source>&Paste</source> + <translation>&چسباندن</translation> + </message> + <message> + <source>Delete</source> + <translation>حذف</translation> + </message> + <message> + <source>Select All</source> + <translation>انتخاب همه</translation> + </message> +</context> +<context> + <name>QLocalServer</name> + <message> + <source>%1: Name error</source> + <translation>%1: خطای نام</translation> + </message> + <message> + <source>%1: Permission denied</source> + <translation>%1: حق دسترسی وجود ندارد</translation> + </message> + <message> + <source>%1: Address in use</source> + <translation>%1: آدرس در حال استفاده است</translation> + </message> + <message> + <source>%1: Unknown error %2</source> + <translation>%1: خطای ناشناخته %2</translation> + </message> +</context> +<context> + <name>QLocalSocket</name> + <message> + <source>%1: Connection refused</source> + <translation>%1: اتصال رد شد</translation> + </message> + <message> + <source>%1: Remote closed</source> + <translation>%1: فرمان از دور بسته شد</translation> + </message> + <message> + <source>%1: Invalid name</source> + <translation>%1: نام نامعتبر</translation> + </message> + <message> + <source>%1: Socket access error</source> + <translation>%1: خطای دسترسی به سوکت</translation> + </message> + <message> + <source>%1: Socket resource error</source> + <translation>%1: خطای منبع سوکت</translation> + </message> + <message> + <source>%1: Socket operation timed out</source> + <translation>%1: زمان عملیات سوکت به اتمام رسید</translation> + </message> + <message> + <source>%1: Datagram too large</source> + <translation>%1: دیتاگرام بیش از حد بزرگ است</translation> + </message> + <message> + <source>%1: Connection error</source> + <translation>%1: خطای اتصال</translation> + </message> + <message> + <source>%1: The socket operation is not supported</source> + <translation>%1: عملیات سوکت پشتیبانی نشده است</translation> + </message> + <message> + <source>%1: Unknown error</source> + <translation>%1: خطای ناشناخته</translation> + </message> + <message> + <source>%1: Unknown error %2</source> + <translation>%1: خطای ناشناخته %2</translation> + </message> +</context> +<context> + <name>QMYSQLDriver</name> + <message> + <source>Unable to open database '</source> + <translation>نمیتوان پایگاه داده را باز کرد '</translation> + </message> + <message> + <source>Unable to connect</source> + <translation>نمیتوان اتصال برقرار نمود</translation> + </message> + <message> + <source>Unable to begin transaction</source> + <translation>نمیتوان تراکنش را شروع کرد</translation> + </message> + <message> + <source>Unable to commit transaction</source> + <translation>نمیتوان تراکنش را ارسال کرد</translation> + </message> + <message> + <source>Unable to rollback transaction</source> + <translation>نمیتوان تراکنش را بازگرداند</translation> + </message> +</context> +<context> + <name>QMYSQLResult</name> + <message> + <source>Unable to fetch data</source> + <translation>عدم موفقیت در واکشی داده</translation> + </message> + <message> + <source>Unable to execute query</source> + <translation>نمیتوان پرسوجو را اجرا کرد</translation> + </message> + <message> + <source>Unable to store result</source> + <translation>نمیتوان نتیجه را ذخیره کرد</translation> + </message> + <message> + <source>Unable to execute next query</source> + <translation>نمیتوان درخواست بعدی را اجرا کرد</translation> + </message> + <message> + <source>Unable to store next result</source> + <translation>نمیتوان نتیجه بعدی را ذخیره کرد</translation> + </message> + <message> + <source>Unable to prepare statement</source> + <translation>نمیتوان عبارت را آماده کرد</translation> + </message> + <message> + <source>Unable to reset statement</source> + <translation>نمیتوان عبارت را بازنشانی کرد</translation> + </message> + <message> + <source>Unable to bind value</source> + <translation>نمیتوان مقدار را مقید کرد</translation> + </message> + <message> + <source>Unable to execute statement</source> + <translation>نمیتوان عبارت را اجرا کرد</translation> + </message> + <message> + <source>Unable to bind outvalues</source> + <translation>نمیتوان مقادیر بیرونی را مقید کرد</translation> + </message> + <message> + <source>Unable to store statement results</source> + <translation>نمیتوان نتایج عبارت را ذخیره کرد</translation> + </message> +</context> +<context> + <name>QMdiArea</name> + <message> + <source>(Untitled)</source> + <translation>(بینام)</translation> + </message> +</context> +<context> + <name>QMdiSubWindow</name> + <message> + <source>- [%1]</source> + <translation>ـ [%1]</translation> + </message> + <message> + <source>%1 - [%2]</source> + <translation>%1 ـ [%2]</translation> + </message> + <message> + <source>Minimize</source> + <translation>کوچک کردن</translation> + </message> + <message> + <source>Maximize</source> + <translation>بزرگ کردن</translation> + </message> + <message> + <source>Unshade</source> + <translation>بازنشانی سایه</translation> + </message> + <message> + <source>Shade</source> + <translation>سایه</translation> + </message> + <message> + <source>Restore Down</source> + <translation>بازیابی به پایین</translation> + </message> + <message> + <source>Restore</source> + <translation>بازیابی</translation> + </message> + <message> + <source>Close</source> + <translation>بستن</translation> + </message> + <message> + <source>Help</source> + <translation>کمک</translation> + </message> + <message> + <source>Menu</source> + <translation>منو</translation> + </message> + <message> + <source>&Restore</source> + <translation>با&زیابی</translation> + </message> + <message> + <source>&Move</source> + <translation>&حرکت</translation> + </message> + <message> + <source>&Size</source> + <translation>&اندازه</translation> + </message> + <message> + <source>Mi&nimize</source> + <translation>کوچ&ک کردن</translation> + </message> + <message> + <source>Ma&ximize</source> + <translation>بزر&گ کردن</translation> + </message> + <message> + <source>Stay on &Top</source> + <translation>بالاتر ب&ماند</translation> + </message> + <message> + <source>&Close</source> + <translation>&بستن</translation> + </message> +</context> +<context> + <name>QMenu</name> + <message> + <source>Close</source> + <translation>بستن</translation> + </message> + <message> + <source>Open</source> + <translation>بازکردن</translation> + </message> + <message> + <source>Execute</source> + <translation>اجرا</translation> + </message> +</context> +<context> + <name>QMenuBar</name> + <message> + <source>Actions</source> + <translation>عمل</translation> + </message> +</context> +<context> + <name>QMessageBox</name> + <message> + <source>Show Details...</source> + <translation>نمایش جزئیات...</translation> + </message> + <message> + <source>Hide Details...</source> + <translation>مخفی کردن جزئیات...</translation> + </message> + <message> + <source>OK</source> + <translation>تأیید</translation> + </message> + <message> + <source>Help</source> + <translation>کمک</translation> + </message> + <message> + <source><h3>About Qt</h3><p>This program uses Qt version %1.</p></source> + <translation><h3>دربارهٔ کیوت</h3><p>این برنامه از کیوت نسخهٔ %1 استفاده میکند.</p></translation> + </message> + <message> + <source><p>Qt is a C++ toolkit for cross-platform application development.</p><p>Qt provides single-source portability across MS&nbsp;Windows, Mac&nbsp;OS&nbsp;X, Linux, and all major commercial Unix variants. Qt is also available for embedded devices as Qt for Embedded Linux and Qt for Windows CE.</p><p>Qt is available under three different licensing options designed to accommodate the needs of our various users.</p><p>Qt licensed under our commercial license agreement is appropriate for development of proprietary/commercial software where you do not want to share any source code with third parties or otherwise cannot comply with the terms of the GNU LGPL version 2.1 or GNU GPL version 3.0.</p><p>Qt licensed under the GNU LGPL version 2.1 is appropriate for the development of Qt applications (proprietary or open source) provided you can comply with the terms and conditions of the GNU LGPL version 2.1.</p><p>Qt licensed under the GNU General Public License version 3.0 is appropriate for the development of Qt applications where you wish to use such applications in combination with software subject to the terms of the GNU GPL version 3.0 or where you are otherwise willing to comply with the terms of the GNU GPL version 3.0.</p><p>Please see <a href="http://qt.nokia.com/products/licensing">qt.nokia.com/products/licensing</a> for an overview of Qt licensing.</p><p>Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).</p><p>Qt is a Nokia product. See <a href="http://qt.nokia.com/">qt.nokia.com</a> for more information.</p></source> + <translation><p dir="rtl">کیوت یک ابزار C++ است که برای توسعهٔ نرمافزار مستقل از پلتفرم به کار میرود</p><p dir="rtl">کیوت قابلیت حمل تکمنبع را برای مایکروسافت ویندوز، مکاواسایکس، لینوکس و تمام توزیعهای اصلی یونیکس پشتیبانی میکند. کیوت همچنین برای دستگاههای جانبی قابل استفاده است. از جمله کیوت برای لینوکس تعبیه شده و کیوت برای ویندوز CE.</p><p dir="rtl">به منظور پاسخدهی به نیاز کاربران مختلف، کیوت تحت سه اجازهنامهٔ متفاوت قابل دستیابی است.</p><p dir="rtl">Qt منتشر شده تحت اجازهنامه تجاری ما برای توسعهٔ تجاری نرمافزارهایی مناسب است که مایل نیستید کد منبع آنها را با اشخاص ثالث و یا دیگران به اشتراک بگذارید یا به هر دلیل نمیتوانید با شرایط GNU LGPL نسخهٔ ۲٫۱ یا GNU GPL نسخهٔ ۳ موافقت کنید.</p><p dir="rtl">Qt منتشر شده تحت اجازهنامهٔ GNU LGPL نسخهٔ ۲٫۱؛ در صورتی که بتوانید با مفاهیم و شرایط GNU LGPL نسخهٔ ۲٫۱ موافقت کنید، برای توسعهٔ برنامههای کاربردی متنباز قابل استفاده است.</p><p dir="rtl">Qt منتشر شده تحت اجازهنامهٔ GNU General Public License نسخهٔ ۳ برای توسعهٔ برنامههایی مناسب است که بخواهید از آنها در ترکیبهایی از نرمافزارهای تحت شمول شرایط GNU GPL نسخهٔ ۳٫۰ استفاده کنید یا مایل باشید با شرایط اجازهنامهٔ GNU GPL نسخهٔ ۳ موافقت کنید.</p><p dir="rtl">برای به دست آوردن اطلاعاتی در مورد اجازهنامههای Qt لطفاً <a href="http://qt.nokia.com/products/licensing">qt.nokia.com/products/licensing</a> را ببینید.</p><p dir="rtl">قانون حمایت از حقوق مؤلفین (C) ۲۰۱۱ کمپانی نوکیا و/یا تمام زیرمجموعهها</p><p dir="rtl">Qt یک محصول Nokia است.برای اطلاعات بیشتر <a href="http://qt.nokia.com/">qt.nokia.com</a> را ببینید.</p></translation> + </message> + <message> + <source>About Qt</source> + <translation>دربارهٔ کیوت</translation> + </message> +</context> +<context> + <name>QMultiInputContext</name> + <message> + <source>Select IM</source> + <translation>انتخاب IM</translation> + </message> +</context> +<context> + <name>QMultiInputContextPlugin</name> + <message> + <source>Multiple input method switcher</source> + <translation>سویچ روش ورودی چندگانه</translation> + </message> + <message> + <source>Multiple input method switcher that uses the context menu of the text widgets</source> + <translation>سویچ روش ورودی چندگانه که از منوی محتوای عناصر متنی استفاده میکند</translation> + </message> +</context> +<context> + <name>QNativeSocketEngine</name> + <message> + <source>Unable to initialize non-blocking socket</source> + <translation>نمیتوان سوکت بلوکبندی نشده را آماده کرد</translation> + </message> + <message> + <source>Unable to initialize broadcast socket</source> + <translation>نمیتوان سوکت پخش را آماده کرد</translation> + </message> + <message> + <source>Attempt to use IPv6 socket on a platform with no IPv6 support</source> + <translation>تلاش برای استفاده از سوکت IPv6 روی پلتفرم بدون پشتیبانی IPv6</translation> + </message> + <message> + <source>The remote host closed the connection</source> + <translation>میزبان کنترل از راه دور اتصال را بست</translation> + </message> + <message> + <source>Network operation timed out</source> + <translation>عملیات شبکه با وقفهٔ زمانی مواجه شد</translation> + </message> + <message> + <source>Out of resources</source> + <translation>خارج از منابع</translation> + </message> + <message> + <source>Unsupported socket operation</source> + <translation>عملیات پشتیبانی نشده سوکت</translation> + </message> + <message> + <source>Protocol type not supported</source> + <translation>نوع پروتکل پشتیبانی نشده است</translation> + </message> + <message> + <source>Invalid socket descriptor</source> + <translation>توصیفکنندهٔ نامعتبر سوکت</translation> + </message> + <message> + <source>Host unreachable</source> + <translation>میزبان در دسترس نیست</translation> + </message> + <message> + <source>Network unreachable</source> + <translation>شبکه در دسترس نیست</translation> + </message> + <message> + <source>Permission denied</source> + <translation>حق دسترسی وجود ندارد</translation> + </message> + <message> + <source>Connection timed out</source> + <translation>اتصال با وقفهٔ زمانی مواجه شد</translation> + </message> + <message> + <source>Connection refused</source> + <translation>اتصال پذیرفته نشد</translation> + </message> + <message> + <source>The bound address is already in use</source> + <translation>آدرس محدوده هماکنون در حال استفاده است</translation> + </message> + <message> + <source>The address is not available</source> + <translation>آدرس در دسترس نیست</translation> + </message> + <message> + <source>The address is protected</source> + <translation>آدرس حفاظتشده است</translation> + </message> + <message> + <source>Datagram was too large to send</source> + <translation>دیتاگرام برای ارسال خیلی بزرگ بود</translation> + </message> + <message> + <source>Unable to send a message</source> + <translation>نمیتوان پیام را ارسال کرد</translation> + </message> + <message> + <source>Unable to receive a message</source> + <translation>نمیتوان پیام دریافت کرد</translation> + </message> + <message> + <source>Unable to write</source> + <translation>ناتوان در نوشتن</translation> + </message> + <message> + <source>Network error</source> + <translation>خطای شبکه</translation> + </message> + <message> + <source>Another socket is already listening on the same port</source> + <translation>سوکت تکیهگاه هماکنون روی همان درگاه در حال شنیدن است</translation> + </message> + <message> + <source>Operation on non-socket</source> + <translation>عملیات روی غیرسوکت</translation> + </message> + <message> + <source>The proxy type is invalid for this operation</source> + <translation>پروکسی برای این عملیات غیرمعتبر است</translation> + </message> + <message> + <source>Unknown error</source> + <translation>خطای ناشناخته</translation> + </message> +</context> +<context> + <name>QNetworkAccessCacheBackend</name> + <message> + <source>Error opening %1</source> + <translation>خطای باز کردن %1</translation> + </message> +</context> +<context> + <name>QNetworkAccessDataBackend</name> + <message> + <source>Operation not supported on %1</source> + <translation>عملیات روی %1 پشتیبانی نمیشود</translation> + </message> + <message> + <source>Invalid URI: %1</source> + <translation>نشانی اینترنتی نامعتبر: %1</translation> + </message> +</context> +<context> + <name>QNetworkAccessDebugPipeBackend</name> + <message> + <source>Write error writing to %1: %2</source> + <translation>خطای نوشتن روی %1: %2</translation> + </message> + <message> + <source>Socket error on %1: %2</source> + <translation>خطای سوکت در %1: %2</translation> + </message> + <message> + <source>Remote host closed the connection prematurely on %1</source> + <translation>میزبان کنترل از راه دور اتصال را نابهنگام روی %1 بست</translation> + </message> +</context> +<context> + <name>QNetworkAccessFileBackend</name> + <message> + <source>Request for opening non-local file %1</source> + <translation>درخواست برای بازکردن پروندهٔ غیر محلی %1</translation> + </message> + <message> + <source>Cannot open %1: Path is a directory</source> + <translation>نمیتوان %1 را باز کرد: مسیر یک پوشه است</translation> + </message> + <message> + <source>Error opening %1: %2</source> + <translation>خطای باز کردن %1: %2</translation> + </message> + <message> + <source>Write error writing to %1: %2</source> + <translation>خطای نوشتن روی %1: %2</translation> + </message> + <message> + <source>Read error reading from %1: %2</source> + <translation>خطای خواندن از %1: %2</translation> + </message> +</context> +<context> + <name>QNetworkAccessFtpBackend</name> + <message> + <source>No suitable proxy found</source> + <translation>پروکسی مناسب پیدا نشد</translation> + </message> + <message> + <source>Cannot open %1: is a directory</source> + <translation>نمیتوان %1 را باز کرد: یک پوشه است</translation> + </message> + <message> + <source>Logging in to %1 failed: authentication required</source> + <translation>.برقراری ناموفق ارتباط با %1: اعتبارسنجی نیاز است</translation> + </message> + <message> + <source>Error while downloading %1: %2</source> + <translation>خطا در هنگام دانلود %1: %2</translation> + </message> + <message> + <source>Error while uploading %1: %2</source> + <translation>خطا در هنگام آپلود %1: %2</translation> + </message> +</context> +<context> + <name>QNetworkAccessHttpBackend</name> + <message> + <source>No suitable proxy found</source> + <translation>پروکسی مناسب پیدا نشد</translation> + </message> +</context> +<context> + <name>QNetworkAccessManager</name> + <message> + <source>Network access is disabled.</source> + <translation>دسترسی شبکه غیرفعال شده است.</translation> + </message> +</context> +<context> + <name>QNetworkReply</name> + <message> + <source>Error downloading %1 - server replied: %2</source> + <translation>خطای دانلود %1 - پاسخ سرور: %2</translation> + </message> + <message> + <source>Protocol "%1" is unknown</source> + <translation>پروتکل «%1» پشتیبانی ناشناخته است</translation> + </message> + <message> + <source>Network session error.</source> + <translation>خطای جلسهٔ شبکه.</translation> + </message> + <message> + <source>Temporary network failure.</source> + <translation>خرابی موقت شبکه.</translation> + </message> +</context> +<context> + <name>QNetworkReplyImpl</name> + <message> + <source>Operation canceled</source> + <translation>عملیات لغو شد</translation> + </message> +</context> +<context> + <name>QNetworkSession</name> + <message> + <source>Invalid configuration.</source> + <translation>پیکربندی نامعتبر.</translation> + </message> +</context> +<context> + <name>QNetworkSessionPrivateImpl</name> + <message> + <source>Roaming error</source> + <translation>خطای رومینگ</translation> + </message> + <message> + <source>Session aborted by user or system</source> + <translation>جلسه بهوسیلهٔ کاربر یا سیستم لغو شد</translation> + </message> + <message> + <source>The specified configuration cannot be used.</source> + <translation>پیکربندی مشخصشده نمیتواند استفاده شود.</translation> + </message> + <message> + <source>Unidentified Error</source> + <translation>خطای ناشناخته</translation> + </message> + <message> + <source>Unknown session error.</source> + <translation>خطای ناشناختهٔ جلسه.</translation> + </message> + <message> + <source>The session was aborted by the user or system.</source> + <translation>جلسه بهوسیلهٔ کاربر یا سیستم لغو شده بود.</translation> + </message> + <message> + <source>The requested operation is not supported by the system.</source> + <translation>درخواست عملیات بهوسیلهٔ سیستم پشتیبانی نشده است.</translation> + </message> + <message> + <source>Roaming was aborted or is not possible.</source> + <translation>رومینگ لغو شد یا امکان پذیر نیست.</translation> + </message> +</context> +<context> + <name>QOCIDriver</name> + <message> + <source>Unable to initialize</source> + <comment>QOCIDriver</comment> + <translation>نمیتوان آماده کرد</translation> + </message> + <message> + <source>Unable to logon</source> + <translation>نمیتوان وارد سیستم شد</translation> + </message> + <message> + <source>Unable to begin transaction</source> + <translation>نمیتوان تراکنش را شروع کرد</translation> + </message> + <message> + <source>Unable to commit transaction</source> + <translation>نمیتوان تراکنش را ارسال کرد</translation> + </message> + <message> + <source>Unable to rollback transaction</source> + <translation>نمیتوان تراکنش را بازگرداند</translation> + </message> +</context> +<context> + <name>QOCIResult</name> + <message> + <source>Unable to bind column for batch execute</source> + <translation>نمیتوان ستون را برای اجرای گروهی مقید کرد</translation> + </message> + <message> + <source>Unable to execute batch statement</source> + <translation>نمیتوان عبارت دستهای را اجرا کرد</translation> + </message> + <message> + <source>Unable to goto next</source> + <translation>نمیتوان به بعدی رفت</translation> + </message> + <message> + <source>Unable to alloc statement</source> + <translation>نمیتوان عبارت را تخصیص داد</translation> + </message> + <message> + <source>Unable to prepare statement</source> + <translation>نمیتوان عبارت را آماده کرد</translation> + </message> + <message> + <source>Unable to get statement type</source> + <translation>نمیتوان نوع عبارت را بازیابی کرد</translation> + </message> + <message> + <source>Unable to bind value</source> + <translation>نمیتوان متغیر را مقید کرد</translation> + </message> + <message> + <source>Unable to execute statement</source> + <translation>نمیتوان عبارت را اجرا کرد</translation> + </message> +</context> +<context> + <name>QODBCDriver</name> + <message> + <source>Unable to connect</source> + <translation>نمیتوان اتصال برقرار کرد</translation> + </message> + <message> + <source>Unable to connect - Driver doesn't support all functionality required</source> + <translation>نمیتوان اتصال برقرار نمود. درایور تمام عملکردهای لازم را پشتیبانی نمیکند</translation> + </message> + <message> + <source>Unable to disable autocommit</source> + <translation>نمیتوان ارسال خودکار را غیرفعال کرد</translation> + </message> + <message> + <source>Unable to commit transaction</source> + <translation>نمیتوان تراکنش را ارسال کرد</translation> + </message> + <message> + <source>Unable to rollback transaction</source> + <translation>نمیتوان تراکنش را بازگرداند</translation> + </message> + <message> + <source>Unable to enable autocommit</source> + <translation>نمیتوان ارسال خودکار را فعال کرد</translation> + </message> +</context> +<context> + <name>QODBCResult</name> + <message> + <source>Unable to fetch last</source> + <translation>نمیتوان آخرین رکورد را واکشی کرد</translation> + </message> + <message> + <source>QODBCResult::reset: Unable to set 'SQL_CURSOR_STATIC' as statement attribute. Please check your ODBC driver configuration</source> + <translation>QODBCResult::reset: نمیتوان 'SQL_CURSOR_STATIC' را به عنوان صفت عبارت نتظیم کرد. لطفاً پیکربندی گردانندهٔ ODBC خود را بررسی کنید</translation> + </message> + <message> + <source>Unable to execute statement</source> + <translation>نمیتوان عبارت را اجرا کرد</translation> + </message> + <message> + <source>Unable to fetch</source> + <translation>نمیتوان رکورد را واکشی کرد</translation> + </message> + <message> + <source>Unable to fetch next</source> + <translation>نمیتوان رکورد بعد را واکشی کرد</translation> + </message> + <message> + <source>Unable to fetch first</source> + <translation>نمیتوان اولین رکورد را واکشی کرد</translation> + </message> + <message> + <source>Unable to fetch previous</source> + <translation>نمیتوان رکورد قبلی را واکشی کرد</translation> + </message> + <message> + <source>Unable to prepare statement</source> + <translation>نمیتوان عبارت را آماده کرد</translation> + </message> + <message> + <source>Unable to bind variable</source> + <translation>نمیتوان متغیر را مقید کرد</translation> + </message> +</context> +<context> + <name>QObject</name> + <message> + <source>PulseAudio Sound Server</source> + <translation>سرویسدهندهٔ صوت PulseAudio</translation> + </message> + <message> + <source>"%1" duplicates a previous role name and will be disabled.</source> + <translation>"%1" نام وظیفهٔ قبلی را تکرار میکند و غیرفعال خواهد شد.</translation> + </message> + <message> + <source>invalid query: "%1"</source> + <translation>پرسوجوی نامعتبر: %1</translation> + </message> +</context> +<context> + <name>QPPDOptionsModel</name> + <message> + <source>Name</source> + <translation>نام</translation> + </message> + <message> + <source>Value</source> + <translation>مقدار</translation> + </message> +</context> +<context> + <name>QPSQLDriver</name> + <message> + <source>Unable to connect</source> + <translation>نمیتوان اتصال برقرار کرد</translation> + </message> + <message> + <source>Could not begin transaction</source> + <translation>نمیتوان تراکنش را شروع کرد</translation> + </message> + <message> + <source>Could not commit transaction</source> + <translation>نمیتوان تراکنش را ارسال کرد</translation> + </message> + <message> + <source>Could not rollback transaction</source> + <translation>نمیتوان تراکنش را بازگرداند</translation> + </message> + <message> + <source>Unable to subscribe</source> + <translation>نمیتوان اشتراک ایجاد کرد</translation> + </message> + <message> + <source>Unable to unsubscribe</source> + <translation>نمیتوان اشتراک را لغو کرد</translation> + </message> +</context> +<context> + <name>QPSQLResult</name> + <message> + <source>Unable to create query</source> + <translation>نمیتوان پرسوجو ایجاد کرد</translation> + </message> + <message> + <source>Unable to prepare statement</source> + <translation>نمیتوان عبارت را آماده کرد</translation> + </message> +</context> +<context> + <name>QPageSetupWidget</name> + <message> + <source>Form</source> + <translation>فرم</translation> + </message> + <message> + <source>Paper</source> + <translation>کاغذ</translation> + </message> + <message> + <source>Page size:</source> + <translation>اندازهٔ صفحه:</translation> + </message> + <message> + <source>Width:</source> + <translation>عرض:</translation> + </message> + <message> + <source>Height:</source> + <translation>ارتفاع:</translation> + </message> + <message> + <source>Paper source:</source> + <translation>منبع کاغذ:</translation> + </message> + <message> + <source>Orientation</source> + <translation>جهت</translation> + </message> + <message> + <source>Portrait</source> + <translation>عمودی</translation> + </message> + <message> + <source>Landscape</source> + <translation>افقی</translation> + </message> + <message> + <source>Reverse landscape</source> + <translation>افقی معکوس</translation> + </message> + <message> + <source>Reverse portrait</source> + <translation>.عمودی معکوس</translation> + </message> + <message> + <source>Margins</source> + <translation>حاشیه</translation> + </message> + <message> + <source>top margin</source> + <translation>حاشیهٔ بالا</translation> + </message> + <message> + <source>left margin</source> + <translation>حاشیهٔ چپ</translation> + </message> + <message> + <source>right margin</source> + <translation>حاشیهٔ راست</translation> + </message> + <message> + <source>bottom margin</source> + <translation>حاشیهٔ پایین</translation> + </message> + <message> + <source>Centimeters (cm)</source> + <translation>سانتیمتر (cm)</translation> + </message> + <message> + <source>Millimeters (mm)</source> + <translation>میلیمتر (mm)</translation> + </message> + <message> + <source>Inches (in)</source> + <translation>اینچ (in)</translation> + </message> + <message> + <source>Points (pt)</source> + <translation>نقطه (pt)</translation> + </message> +</context> +<context> + <name>QPluginLoader</name> + <message> + <source>The plugin was not loaded.</source> + <translation>افزونه بار نشده بود.</translation> + </message> + <message> + <source>Unknown error</source> + <translation>خطای ناشناخته</translation> + </message> +</context> +<context> + <name>QPrintDialog</name> + <message> + <source>Print</source> + <translation>چاپ</translation> + </message> + <message> + <source>A0</source> + <translation>A0</translation> + </message> + <message> + <source>A1</source> + <translation>A1</translation> + </message> + <message> + <source>A2</source> + <translation>A2</translation> + </message> + <message> + <source>A3</source> + <translation>A3</translation> + </message> + <message> + <source>A4</source> + <translation>A4</translation> + </message> + <message> + <source>A5</source> + <translation>A5</translation> + </message> + <message> + <source>A6</source> + <translation>A6</translation> + </message> + <message> + <source>A7</source> + <translation>A7</translation> + </message> + <message> + <source>A8</source> + <translation>A8</translation> + </message> + <message> + <source>A9</source> + <translation>A9</translation> + </message> + <message> + <source>B0</source> + <translation>B0</translation> + </message> + <message> + <source>B1</source> + <translation>B1</translation> + </message> + <message> + <source>B2</source> + <translation>B2</translation> + </message> + <message> + <source>B3</source> + <translation>B3</translation> + </message> + <message> + <source>B4</source> + <translation>B4</translation> + </message> + <message> + <source>B5</source> + <translation>B5</translation> + </message> + <message> + <source>B6</source> + <translation>B6</translation> + </message> + <message> + <source>B7</source> + <translation>B7</translation> + </message> + <message> + <source>B8</source> + <translation>B8</translation> + </message> + <message> + <source>B9</source> + <translation>B9</translation> + </message> + <message> + <source>B10</source> + <translation>B10</translation> + </message> + <message> + <source>C5E</source> + <translation>C5E</translation> + </message> + <message> + <source>DLE</source> + <translation>DLE</translation> + </message> + <message> + <source>Executive</source> + <translation>Executive</translation> + </message> + <message> + <source>Folio</source> + <translation>Folio</translation> + </message> + <message> + <source>Ledger</source> + <translation>Ledger</translation> + </message> + <message> + <source>Legal</source> + <translation>Legal</translation> + </message> + <message> + <source>Letter</source> + <translation>Letter</translation> + </message> + <message> + <source>Tabloid</source> + <translation>Tabloid</translation> + </message> + <message> + <source>US Common #10 Envelope</source> + <translation>US Common #10 Envelope</translation> + </message> + <message> + <source>Custom</source> + <translation>سفارشی</translation> + </message> + <message> + <source>File exists</source> + <translation>پرونده وجود دارد</translation> + </message> + <message> + <source><qt>Do you want to overwrite it?</qt></source> + <translation><qt>آیا میخواهید آن را بازنویسی کنید؟</qt></translation> + </message> + <message> + <source>A0 (841 x 1189 mm)</source> + <translation>A0 (۸۴۱ x ۱۱۸۹ میلیمتر)</translation> + </message> + <message> + <source>A1 (594 x 841 mm)</source> + <translation>A1 (۵۹۴ x ۸۴۱ میلیمتر)</translation> + </message> + <message> + <source>A2 (420 x 594 mm)</source> + <translation>A2 (۴۲۰ x ۵۹۴ میلیمتر)</translation> + </message> + <message> + <source>A3 (297 x 420 mm)</source> + <translation>A3 (۲۹۷ x ۴۲۰ میلیمتر)</translation> + </message> + <message> + <source>A4 (210 x 297 mm, 8.26 x 11.7 inches)</source> + <translation>A4 (۲۱۰ x ۲۹۷ میلیمتر، ۸٫۲۶ x ۱۱٫۷ اینچ)</translation> + </message> + <message> + <source>A5 (148 x 210 mm)</source> + <translation>A5 (۱۴۸ x ۲۱۰ میلیمتر)</translation> + </message> + <message> + <source>A6 (105 x 148 mm)</source> + <translation>A6 (۱۰۵ x ۱۴۸ میلیمتر)</translation> + </message> + <message> + <source>A7 (74 x 105 mm)</source> + <translation>A7 (۷۴ x ۱۰۵ میلیمتر)</translation> + </message> + <message> + <source>A8 (52 x 74 mm)</source> + <translation>A8 (۵۲ x ۷۴ میلیمتر)</translation> + </message> + <message> + <source>A9 (37 x 52 mm)</source> + <translation>A9 (۳۷ x ۵۲ mm)</translation> + </message> + <message> + <source>B0 (1000 x 1414 mm)</source> + <translation>B0 (۱۰۰۰ x ۱۴۱۴ میلیمتر)</translation> + </message> + <message> + <source>B1 (707 x 1000 mm)</source> + <translation>B1 (۷۰۷ x ۱۰۰۰ میلیمتر)</translation> + </message> + <message> + <source>B2 (500 x 707 mm)</source> + <translation>B2 (۵۰۰ x ۷۰۷ میلیمتر)</translation> + </message> + <message> + <source>B3 (353 x 500 mm)</source> + <translation>B3 (۳۵۳ x ۵۰۰ میلیمتر)</translation> + </message> + <message> + <source>B4 (250 x 353 mm)</source> + <translation>B4 (۲۵۰ x ۳۵۳ میلیمتر)</translation> + </message> + <message> + <source>B5 (176 x 250 mm, 6.93 x 9.84 inches)</source> + <translation>B5 (۱۷۶ x ۲۵۰ میلیمتر، ۶٫۹۳ x ۹٫۸۴ اینچ)</translation> + </message> + <message> + <source>B6 (125 x 176 mm)</source> + <translation>B6 (۱۲۵ x ۱۷۶ میلیمتر)</translation> + </message> + <message> + <source>B7 (88 x 125 mm)</source> + <translation>B7 (۸۸ x ۱۲۵ میلیمتر)</translation> + </message> + <message> + <source>B8 (62 x 88 mm)</source> + <translation>B8 (۶۲ x ۸۸ میلیمتر)</translation> + </message> + <message> + <source>B9 (44 x 62 mm)</source> + <translation>B9 (۴۴ x ۶۲ میلیمتر)</translation> + </message> + <message> + <source>B10 (31 x 44 mm)</source> + <translation>B10 (۳۱ x ۴۴ میلیمتر)</translation> + </message> + <message> + <source>C5E (163 x 229 mm)</source> + <translation>C5E (۱۶۳ x ۲۲۹ میلیمتر)</translation> + </message> + <message> + <source>DLE (110 x 220 mm)</source> + <translation>DLE (۱۱۰ x ۲۲۰ میلیمتر)</translation> + </message> + <message> + <source>Executive (7.5 x 10 inches, 191 x 254 mm)</source> + <translation>Executive (۷٫۵ x ۱۰ اینچ - ۱۹۱ x ۲۵۴ میلیمتر)</translation> + </message> + <message> + <source>Folio (210 x 330 mm)</source> + <translation>Folio (۲۱۰ x ۳۳۰ میلیمتر)</translation> + </message> + <message> + <source>Ledger (432 x 279 mm)</source> + <translation>Ledger (۴۳۲ x ۲۷۹ میلیمتر)</translation> + </message> + <message> + <source>Legal (8.5 x 14 inches, 216 x 356 mm)</source> + <translation>Legal (۸٫۵ x ۱۴ اینچ - ۲۱۶ x ۳۵۶ میلیمتر)</translation> + </message> + <message> + <source>Letter (8.5 x 11 inches, 216 x 279 mm)</source> + <translation>Letter (۸٫۵ x ۱۱ اینچ - ۲۱۶ x ۲۹۷ میلیمتر)</translation> + </message> + <message> + <source>Tabloid (279 x 432 mm)</source> + <translation>Tabloid (۲۷۹ x ۴۳۲ میلیمتر)</translation> + </message> + <message> + <source>US Common #10 Envelope (105 x 241 mm)</source> + <translation>US Common #10 Envelope (۱۰۵ x ۲۴۱ میلیمتر)</translation> + </message> + <message> + <source>Print all</source> + <translation>چاپ کردن همه</translation> + </message> + <message> + <source>Print selection</source> + <translation>اتتخاب چاپ</translation> + </message> + <message> + <source>Print range</source> + <translation>چاپ کردن محدوده</translation> + </message> + <message> + <source>Print current page</source> + <translation>چاپ صفحهٔ جاری</translation> + </message> + <message> + <source>&Options >></source> + <translation>&تنظیمات >></translation> + </message> + <message> + <source>&Print</source> + <translation>&چاپ کردن</translation> + </message> + <message> + <source>&Options <<</source> + <translation>&تنظیمات <<</translation> + </message> + <message> + <source>Print to File (PDF)</source> + <translation>چاپ کردن روی پرونده (PDF)</translation> + </message> + <message> + <source>Print to File (Postscript)</source> + <translation>چاپ کردن روی پرونده (Postscript)</translation> + </message> + <message> + <source>Local file</source> + <translation>پروندهٔ محلی</translation> + </message> + <message> + <source>Write %1 file</source> + <translation>نوشتن %1 فایل</translation> + </message> + <message> + <source>Print To File ...</source> + <translation>چاپ روی پرونده ...</translation> + </message> + <message> + <source>%1 is a directory. +Please choose a different file name.</source> + <translation>%1 یک پوشه است +لطفا یک پروندهٔ دیگر انتخاب کنید.</translation> + </message> + <message> + <source>File %1 is not writable. +Please choose a different file name.</source> + <translation>پروندهٔ %1 قابل نوشتن نیست +لطفاً یک پروندهٔ دیگر انتخاب کنید.</translation> + </message> + <message> + <source>%1 already exists. +Do you want to overwrite it?</source> + <translation>%1 هماکنون وجود دارد +آیا میخواهید آن را بازنویسی کنید؟</translation> + </message> + <message> + <source>The 'From' value cannot be greater than the 'To' value.</source> + <translation>مقدار مبدأ نمیتواند از مقدار مقصد بزرگتر باشد.</translation> + </message> + <message> + <source>OK</source> + <translation>تأیید</translation> + </message> + <message> + <source>locally connected</source> + <translation>به طورمحلی متصل شد</translation> + </message> + <message> + <source>Aliases: %1</source> + <translation>نامهای مستعار: %1</translation> + </message> + <message> + <source>unknown</source> + <translation>ناشناخته</translation> + </message> +</context> +<context> + <name>QPrintPreviewDialog</name> + <message> + <source>Page Setup</source> + <translation>پیکربندی صفحه</translation> + </message> + <message> + <source>%1%</source> + <translation>%1%</translation> + </message> + <message> + <source>Print Preview</source> + <translation>پیشنمایش چاپ</translation> + </message> + <message> + <source>Next page</source> + <translation>صفحهٔ بعدی</translation> + </message> + <message> + <source>Previous page</source> + <translation>صفحهٔ قبلی</translation> + </message> + <message> + <source>First page</source> + <translation>صفحهٔ اول</translation> + </message> + <message> + <source>Last page</source> + <translation>صفحهٔ آخر</translation> + </message> + <message> + <source>Fit width</source> + <translation>تنظیم براساس عرض</translation> + </message> + <message> + <source>Fit page</source> + <translation>تنظیم براساس اندازهٔ صفحه</translation> + </message> + <message> + <source>Zoom in</source> + <translation>بزرگنمایی</translation> + </message> + <message> + <source>Zoom out</source> + <translation>کوچکنمایی</translation> + </message> + <message> + <source>Portrait</source> + <translation>عمودی</translation> + </message> + <message> + <source>Landscape</source> + <translation>افقی</translation> + </message> + <message> + <source>Show single page</source> + <translation>نمایش یک صفحهٔ تکی</translation> + </message> + <message> + <source>Show facing pages</source> + <translation>نمایش صفحههای اول</translation> + </message> + <message> + <source>Show overview of all pages</source> + <translation>نمایش اختصاری تمام صفحات</translation> + </message> + <message> + <source>Print</source> + <translation>چاپ</translation> + </message> + <message> + <source>Page setup</source> + <translation>پیکربندی صفحه</translation> + </message> + <message> + <source>Close</source> + <translation>بستن</translation> + </message> + <message> + <source>Export to PDF</source> + <translation>خروجی گرفتن به PDF</translation> + </message> + <message> + <source>Export to PostScript</source> + <translation>خروجی گرفتن به PostScript</translation> + </message> +</context> +<context> + <name>QPrintPropertiesWidget</name> + <message> + <source>Form</source> + <translation>فرم</translation> + </message> + <message> + <source>Page</source> + <translation>صفحه</translation> + </message> + <message> + <source>Advanced</source> + <translation>پیشرفته</translation> + </message> +</context> +<context> + <name>QPrintSettingsOutput</name> + <message> + <source>Form</source> + <translation>فرم</translation> + </message> + <message> + <source>Copies</source> + <translation>کپیها</translation> + </message> + <message> + <source>Print range</source> + <translation>چاپ کردن محدوده</translation> + </message> + <message> + <source>Print all</source> + <translation>چاپ کردن همه</translation> + </message> + <message> + <source>Pages from</source> + <translation>محدودهٔ صفحات</translation> + </message> + <message> + <source>to</source> + <translation>تا</translation> + </message> + <message> + <source>Current Page</source> + <translation>صفحهٔ جاری</translation> + </message> + <message> + <source>Selection</source> + <translation>انتخاب</translation> + </message> + <message> + <source>Output Settings</source> + <translation>تنظیمات خروجی</translation> + </message> + <message> + <source>Copies:</source> + <translation>کپیها:</translation> + </message> + <message> + <source>Collate</source> + <translation>تلفیق کردن</translation> + </message> + <message> + <source>Reverse</source> + <translation>معکوس</translation> + </message> + <message> + <source>Options</source> + <translation>تنظیمات</translation> + </message> + <message> + <source>Color Mode</source> + <translation>حالت رنگ</translation> + </message> + <message> + <source>Color</source> + <translation>رنگ</translation> + </message> + <message> + <source>Grayscale</source> + <translation>مقیاس خاکستری</translation> + </message> + <message> + <source>Duplex Printing</source> + <translation>چاپ دوبله</translation> + </message> + <message> + <source>None</source> + <translation>هیچ</translation> + </message> + <message> + <source>Long side</source> + <translation>سمت طولانی</translation> + </message> + <message> + <source>Short side</source> + <translation>سمت کوتاه</translation> + </message> +</context> +<context> + <name>QPrintWidget</name> + <message> + <source>Form</source> + <translation>فرم</translation> + </message> + <message> + <source>Printer</source> + <translation>چاپگر</translation> + </message> + <message> + <source>&Name:</source> + <translation>&نام:</translation> + </message> + <message> + <source>P&roperties</source> + <translation>و&ژگیها</translation> + </message> + <message> + <source>Location:</source> + <translation>موقعیت:</translation> + </message> + <message> + <source>Preview</source> + <translation>پیشنمایش</translation> + </message> + <message> + <source>Type:</source> + <translation>نوع:</translation> + </message> + <message> + <source>Output &file:</source> + <translation>&پروندهٔ خروجی:</translation> + </message> + <message> + <source>...</source> + <translation>...</translation> + </message> +</context> +<context> + <name>QProcess</name> + <message> + <source>Error reading from process</source> + <translation>خطای خواندن از پردازش</translation> + </message> + <message> + <source>Error writing to process</source> + <translation>خطای نوشتن روی پردازش</translation> + </message> + <message> + <source>Process crashed</source> + <translation>پردازش خراب شد</translation> + </message> + <message> + <source>No program defined</source> + <translation>هیچ برنامهای تعریف نشده است</translation> + </message> + <message> + <source>Could not open input redirection for reading</source> + <translation>نمیتوان تغییر مسیر ورودی را برای خواندن باز کرد</translation> + </message> + <message> + <source>Could not open output redirection for writing</source> + <translation>نمیتوان تغییر مسیر خروجی را برای نوشتن باز کرد</translation> + </message> + <message> + <source>Resource error (fork failure): %1</source> + <translation>خطای منبع (خرابی انشعاب): %1</translation> + </message> + <message> + <source>Process operation timed out</source> + <translation>عملیات پردازش با وقفهٔ زمانی مواجه شد</translation> + </message> + <message> + <source>Process failed to start: %1</source> + <translation>شروع ناموفق پردازش: %1</translation> + </message> +</context> +<context> + <name>QProgressDialog</name> + <message> + <source>Cancel</source> + <translation>لغو</translation> + </message> +</context> +<context> + <name>QPushButton</name> + <message> + <source>Open</source> + <translation>باز کردن</translation> + </message> +</context> +<context> + <name>QRadioButton</name> + <message> + <source>Check</source> + <translation>انتخاب</translation> + </message> +</context> +<context> + <name>QRegExp</name> + <message> + <source>no error occurred</source> + <translation>خطایی رخ نداد</translation> + </message> + <message> + <source>disabled feature used</source> + <translation>استفاده از ویژگی غیرفعال شده</translation> + </message> + <message> + <source>bad char class syntax</source> + <translation>.استفاده از کلاس نویسهٔ نامعتبر</translation> + </message> + <message> + <source>bad lookahead syntax</source> + <translation>نحو نامعتبر پیشرو</translation> + </message> + <message> + <source>bad repetition syntax</source> + <translation>نحو نامعتبر تکرار</translation> + </message> + <message> + <source>invalid octal value</source> + <translation>مقدار هشتهشتی نامعتبر</translation> + </message> + <message> + <source>missing left delim</source> + <translation>جداکنندهٔ چپ موجود نیست</translation> + </message> + <message> + <source>unexpected end</source> + <translation>انتهای نامنتظره</translation> + </message> + <message> + <source>met internal limit</source> + <translation>رویارویی با محدودیت داخلی</translation> + </message> + <message> + <source>invalid interval</source> + <translation>وقفهٔ نامعتبر</translation> + </message> + <message> + <source>invalid category</source> + <translation>طبقهبندی نامعتبر</translation> + </message> +</context> +<context> + <name>QSQLite2Driver</name> + <message> + <source>Error opening database</source> + <translation>خطا در باز کردن پایگاه داده</translation> + </message> + <message> + <source>Unable to begin transaction</source> + <translation>نمیتوان تراکنش داده را شروع کرد</translation> + </message> + <message> + <source>Unable to commit transaction</source> + <translation>نمیتوان تراکنش را ارسال کرد</translation> + </message> + <message> + <source>Unable to rollback transaction</source> + <translation>نمیتوان تراکنش را بازگرداند</translation> + </message> +</context> +<context> + <name>QSQLite2Result</name> + <message> + <source>Unable to fetch results</source> + <translation>عدم موفقیت در واکشی نتایج</translation> + </message> + <message> + <source>Unable to execute statement</source> + <translation>نمیتوان عبارت را اجرا کرد</translation> + </message> +</context> +<context> + <name>QSQLiteDriver</name> + <message> + <source>Error opening database</source> + <translation>خطا در باز کردن پایگاه داده</translation> + </message> + <message> + <source>Error closing database</source> + <translation>خطا در بستن پایگاه داده</translation> + </message> + <message> + <source>Unable to begin transaction</source> + <translation>نمیتوان تراکنش را شروع کرد</translation> + </message> + <message> + <source>Unable to commit transaction</source> + <translation>نمیتوان تراکنش را ارسال کرد</translation> + </message> + <message> + <source>Unable to rollback transaction</source> + <translation>نمیتوان تراکنش را بازگرداند</translation> + </message> +</context> +<context> + <name>QSQLiteResult</name> + <message> + <source>Unable to fetch row</source> + <translation>نمیتوان رکورد را واکشی کرد</translation> + </message> + <message> + <source>No query</source> + <translation>درخواست وجود ندارد</translation> + </message> + <message> + <source>Unable to execute statement</source> + <translation>نمیتوان عبارت را اجرا کرد</translation> + </message> + <message> + <source>Unable to reset statement</source> + <translation>نمیتوان عبارت را بازنشانی کرد</translation> + </message> + <message> + <source>Unable to bind parameters</source> + <translation>نمیتوان پارامترها را مقید کرد</translation> + </message> + <message> + <source>Parameter count mismatch</source> + <translation>تعداد پارامترها تطابق ندارد</translation> + </message> +</context> +<context> + <name>QScriptBreakpointsModel</name> + <message> + <source>ID</source> + <translation>شمارهٔ شناسایی</translation> + </message> + <message> + <source>Location</source> + <translation>موقعیت</translation> + </message> + <message> + <source>Condition</source> + <translation>شرایط</translation> + </message> + <message> + <source>Ignore-count</source> + <translation>نادیدهگرفتن-شمارش</translation> + </message> + <message> + <source>Single-shot</source> + <translation>تک-شلیک</translation> + </message> + <message> + <source>Hit-count</source> + <translation>ضربه-شمارش</translation> + </message> +</context> +<context> + <name>QScriptBreakpointsWidget</name> + <message> + <source>New</source> + <translation>جدید</translation> + </message> + <message> + <source>Delete</source> + <translation>حذف</translation> + </message> +</context> +<context> + <name>QScriptDebugger</name> + <message> + <source>Go to Line</source> + <translation>برو به خط</translation> + </message> + <message> + <source>Line:</source> + <translation>خط:</translation> + </message> + <message> + <source>Interrupt</source> + <translation>وقفه</translation> + </message> + <message> + <source>Shift+F5</source> + <translation>Shift+F5</translation> + </message> + <message> + <source>Continue</source> + <translation>ادامه</translation> + </message> + <message> + <source>F5</source> + <translation>F5</translation> + </message> + <message> + <source>Step Into</source> + <translation>پرش به داخل</translation> + </message> + <message> + <source>F11</source> + <translation>F11</translation> + </message> + <message> + <source>Step Over</source> + <translation>پرش از روی</translation> + </message> + <message> + <source>F10</source> + <translation>F10</translation> + </message> + <message> + <source>Step Out</source> + <translation>پرش به بیرون</translation> + </message> + <message> + <source>Shift+F11</source> + <translation>Shift+F11</translation> + </message> + <message> + <source>Run to Cursor</source> + <translation>اجرا تا نشانگر</translation> + </message> + <message> + <source>Ctrl+F10</source> + <translation>Ctrl+F10</translation> + </message> + <message> + <source>Run to New Script</source> + <translation>اجرا تا اسکریپت جدید</translation> + </message> + <message> + <source>Toggle Breakpoint</source> + <translation>تغییر وضعیت دادن نقطهٔ شکست</translation> + </message> + <message> + <source>F9</source> + <translation>F9</translation> + </message> + <message> + <source>Clear Debug Output</source> + <translation>پاک کردن خروجی اشکالزدایی</translation> + </message> + <message> + <source>Clear Error Log</source> + <translation>پاک کردن گزارش خطا</translation> + </message> + <message> + <source>Clear Console</source> + <translation>پاک کردن کنسول</translation> + </message> + <message> + <source>&Find in Script...</source> + <translation>&پیدا کردن در اسکریپت...</translation> + </message> + <message> + <source>Ctrl+F</source> + <translation>Ctrl+F</translation> + </message> + <message> + <source>Find &Next</source> + <translation>پیدا کردن &بعدی</translation> + </message> + <message> + <source>F3</source> + <translation>F3</translation> + </message> + <message> + <source>Find &Previous</source> + <translation>پیدا کردن &قبلی</translation> + </message> + <message> + <source>Shift+F3</source> + <translation>Shift+F3</translation> + </message> + <message> + <source>Ctrl+G</source> + <translation>Ctrl+G</translation> + </message> + <message> + <source>Debug</source> + <translation>اشکالزدایی</translation> + </message> +</context> +<context> + <name>QScriptDebuggerCodeFinderWidget</name> + <message> + <source>Close</source> + <translation>بستن</translation> + </message> + <message> + <source>Previous</source> + <translation>قبلی</translation> + </message> + <message> + <source>Next</source> + <translation>بعدی</translation> + </message> + <message> + <source>Case Sensitive</source> + <translation>حساس به بزگ و کوچک بودن نویسهها</translation> + </message> + <message> + <source>Whole words</source> + <translation>تمام واژهها</translation> + </message> + <message> + <source><img src=":/qt/scripttools/debugging/images/wrap.png">&nbsp;Search wrapped</source> + <translation><img src=":/qt/scripttools/debugging/images/wrap.png">&nbsp;جستجو پیچیده شد</translation> + </message> +</context> +<context> + <name>QScriptDebuggerLocalsModel</name> + <message> + <source>Name</source> + <translation>نام</translation> + </message> + <message> + <source>Value</source> + <translation>مقدار</translation> + </message> +</context> +<context> + <name>QScriptDebuggerStackModel</name> + <message> + <source>Level</source> + <translation>سطح</translation> + </message> + <message> + <source>Name</source> + <translation>نام</translation> + </message> + <message> + <source>Location</source> + <translation>موقعیت</translation> + </message> +</context> +<context> + <name>QScriptEdit</name> + <message> + <source>Toggle Breakpoint</source> + <translation>تغییر دادن وضعیت نقطهٔ شکست</translation> + </message> + <message> + <source>Disable Breakpoint</source> + <translation>غیرفعال کردن نقطهٔ شکست</translation> + </message> + <message> + <source>Enable Breakpoint</source> + <translation>فعالسازی نقطهٔ شکست</translation> + </message> + <message> + <source>Breakpoint Condition:</source> + <translation>شرط نقطهٔ شکست:</translation> + </message> +</context> +<context> + <name>QScriptEngineDebugger</name> + <message> + <source>Loaded Scripts</source> + <translation>اسکریپت بارگذاریشده</translation> + </message> + <message> + <source>Breakpoints</source> + <translation>نقطهٔ شکست</translation> + </message> + <message> + <source>Stack</source> + <translation>پشته</translation> + </message> + <message> + <source>Locals</source> + <translation>محلیها</translation> + </message> + <message> + <source>Console</source> + <translation>کنسول</translation> + </message> + <message> + <source>Debug Output</source> + <translation>خروجی اشکالزدایی</translation> + </message> + <message> + <source>Error Log</source> + <translation>گزارش خطا</translation> + </message> + <message> + <source>Search</source> + <translation>جستجو</translation> + </message> + <message> + <source>View</source> + <translation>نمایش</translation> + </message> + <message> + <source>Qt Script Debugger</source> + <translation>اشکالزدای اسکریپتی کیوت</translation> + </message> +</context> +<context> + <name>QScriptNewBreakpointWidget</name> + <message> + <source>Close</source> + <translation>بستن</translation> + </message> +</context> +<context> + <name>QScrollBar</name> + <message> + <source>Scroll here</source> + <translation>لغزش به اینجا</translation> + </message> + <message> + <source>Left edge</source> + <translation>گوشهٔ چپ</translation> + </message> + <message> + <source>Top</source> + <translation>بالا</translation> + </message> + <message> + <source>Right edge</source> + <translation>گوشهٔ راست</translation> + </message> + <message> + <source>Bottom</source> + <translation>پایین</translation> + </message> + <message> + <source>Page left</source> + <translation>صفحهٔ چپ</translation> + </message> + <message> + <source>Page up</source> + <translation>صفحهٔ بالا</translation> + </message> + <message> + <source>Page right</source> + <translation>صفحهٔ راست</translation> + </message> + <message> + <source>Page down</source> + <translation>صفحه به پایین</translation> + </message> + <message> + <source>Scroll left</source> + <translation>لغزش به چپ</translation> + </message> + <message> + <source>Scroll up</source> + <translation>لغزش به بالا</translation> + </message> + <message> + <source>Scroll right</source> + <translation>لغزش به راست</translation> + </message> + <message> + <source>Scroll down</source> + <translation>لغزش به پایین</translation> + </message> + <message> + <source>Line up</source> + <translation>به خط شدن</translation> + </message> + <message> + <source>Position</source> + <translation>موقعیت</translation> + </message> + <message> + <source>Line down</source> + <translation>به خط شدن به پایین</translation> + </message> +</context> +<context> + <name>QSharedMemory</name> + <message> + <source>%1: unable to set key on lock</source> + <translation>%1: نمیتوان کلید را روی قفل تنظیم کرد</translation> + </message> + <message> + <source>%1: create size is less then 0</source> + <translation>%1: اندازهٔ ساخت کمتر از صفر است</translation> + </message> + <message> + <source>%1: unable to lock</source> + <translation>%1: نمیتوان قفل کرد</translation> + </message> + <message> + <source>%1: unable to unlock</source> + <translation>%1: نمیتوان قفل را باز کرد</translation> + </message> + <message> + <source>%1: already exists</source> + <translation>%1: هماکنون موجود است</translation> + </message> + <message> + <source>%1: doesn't exists</source> + <translation>%1: وجود ندارد</translation> + </message> + <message> + <source>%1: invalid size</source> + <translation>%1: اندازهٔ نامعتبر</translation> + </message> + <message> + <source>%1: out of resources</source> + <translation>%1: خارج از منابع</translation> + </message> + <message> + <source>%1: permission denied</source> + <translation>%1: حق دسترسی وجود ندارد</translation> + </message> + <message> + <source>%1: unknown error %2</source> + <translation>%1: خطای ناشناخته %2</translation> + </message> + <message> + <source>%1: key error</source> + <translation>%1: خطای کلید</translation> + </message> + <message> + <source>%1: unable to make key</source> + <translation>%1: نمیتوان کلید ایجاد کرد</translation> + </message> + <message> + <source>%1: doesn't exist</source> + <translation>%1: وجود ندارد</translation> + </message> + <message> + <source>%1: key is empty</source> + <translation>%1: کلید تهی است</translation> + </message> + <message> + <source>%1: UNIX key file doesn't exist</source> + <translation>%1: پروندهٔ کلید UNIX وجود ندارد</translation> + </message> + <message> + <source>%1: ftok failed</source> + <translation>%1: عدم موفقیت ftok</translation> + </message> + <message> + <source>%1: system-imposed size restrictions</source> + <translation>%1: محدودیت اندازهٔ تحمیلی سیستم</translation> + </message> + <message> + <source>%1: not attached</source> + <translation>%1: ضمیمه نشد</translation> + </message> + <message> + <source>%1: size query failed</source> + <translation>%1: عدم موفقیت اندازهٔ پرسوجو</translation> + </message> +</context> +<context> + <name>QShortcut</name> + <message> + <source>Space</source> + <extracomment>This and all following "incomprehensible" strings in QShortcut context are key names. Please use the localized names appearing on actual keyboards or whatever is commonly used.</extracomment> + <translation>Space</translation> + </message> + <message> + <source>Esc</source> + <translation>Esc</translation> + </message> + <message> + <source>Tab</source> + <translation>Tab</translation> + </message> + <message> + <source>Backtab</source> + <translation>Backtab</translation> + </message> + <message> + <source>Backspace</source> + <translation>Backspace</translation> + </message> + <message> + <source>Return</source> + <translation>Return</translation> + </message> + <message> + <source>Enter</source> + <translation>Enter</translation> + </message> + <message> + <source>Ins</source> + <translation>Ins</translation> + </message> + <message> + <source>Del</source> + <translation>Del</translation> + </message> + <message> + <source>Pause</source> + <translation>Pause</translation> + </message> + <message> + <source>Print</source> + <translation>Print</translation> + </message> + <message> + <source>SysReq</source> + <translation>SysReq</translation> + </message> + <message> + <source>Home</source> + <translation>Home</translation> + </message> + <message> + <source>End</source> + <translation>End</translation> + </message> + <message> + <source>Left</source> + <translation>Left</translation> + </message> + <message> + <source>Up</source> + <translation>Up</translation> + </message> + <message> + <source>Right</source> + <translation>Right</translation> + </message> + <message> + <source>Down</source> + <translation>Down</translation> + </message> + <message> + <source>PgUp</source> + <translation>PgUp</translation> + </message> + <message> + <source>PgDown</source> + <translation>PgDown</translation> + </message> + <message> + <source>CapsLock</source> + <translation>CapsLock</translation> + </message> + <message> + <source>NumLock</source> + <translation>NumLock</translation> + </message> + <message> + <source>ScrollLock</source> + <translation>ScrollLock</translation> + </message> + <message> + <source>Menu</source> + <translation>Menu</translation> + </message> + <message> + <source>Help</source> + <translation>Help</translation> + </message> + <message> + <source>Back</source> + <translation>Back</translation> + </message> + <message> + <source>Forward</source> + <translation>Forward</translation> + </message> + <message> + <source>Stop</source> + <translation>Stop</translation> + </message> + <message> + <source>Refresh</source> + <translation>Refresh</translation> + </message> + <message> + <source>Volume Down</source> + <translation>Volume Down</translation> + </message> + <message> + <source>Volume Mute</source> + <translation>Volume Mute</translation> + </message> + <message> + <source>Volume Up</source> + <translation>Volume Up</translation> + </message> + <message> + <source>Bass Boost</source> + <translation>Bass Boost</translation> + </message> + <message> + <source>Bass Up</source> + <translation>Bass Up</translation> + </message> + <message> + <source>Bass Down</source> + <translation>Bass Down</translation> + </message> + <message> + <source>Treble Up</source> + <translation>Treble Up</translation> + </message> + <message> + <source>Treble Down</source> + <translation>Treble Down</translation> + </message> + <message> + <source>Media Play</source> + <translation>Media Play</translation> + </message> + <message> + <source>Media Stop</source> + <translation>Media Stop</translation> + </message> + <message> + <source>Media Previous</source> + <translation>Media Previous</translation> + </message> + <message> + <source>Media Next</source> + <translation>Media Next</translation> + </message> + <message> + <source>Media Record</source> + <translation>Media Record</translation> + </message> + <message> + <source>Media Pause</source> + <extracomment>Media player pause button</extracomment> + <translation>Media Pause</translation> + </message> + <message> + <source>Toggle Media Play/Pause</source> + <extracomment>Media player button to toggle between playing and paused</extracomment> + <translation>Toggle Media Play/Pause</translation> + </message> + <message> + <source>Home Page</source> + <translation>Home Page</translation> + </message> + <message> + <source>Favorites</source> + <translation>Favorites</translation> + </message> + <message> + <source>Search</source> + <translation>Search</translation> + </message> + <message> + <source>Standby</source> + <translation>Standby</translation> + </message> + <message> + <source>Open URL</source> + <translation>Open URL</translation> + </message> + <message> + <source>Launch Mail</source> + <translation>Launch Mail</translation> + </message> + <message> + <source>Launch Media</source> + <translation>Launch Media</translation> + </message> + <message> + <source>Launch (0)</source> + <translation>Launch (0)</translation> + </message> + <message> + <source>Launch (1)</source> + <translation>Launch (1)</translation> + </message> + <message> + <source>Launch (2)</source> + <translation>Launch (2)</translation> + </message> + <message> + <source>Launch (3)</source> + <translation>Launch (3)</translation> + </message> + <message> + <source>Launch (4)</source> + <translation>Launch (4)</translation> + </message> + <message> + <source>Launch (5)</source> + <translation>Launch (5)</translation> + </message> + <message> + <source>Launch (6)</source> + <translation>Launch (6)</translation> + </message> + <message> + <source>Launch (7)</source> + <translation>Launch (7)</translation> + </message> + <message> + <source>Launch (8)</source> + <translation>Launch (8)</translation> + </message> + <message> + <source>Launch (9)</source> + <translation>Launch (9)</translation> + </message> + <message> + <source>Launch (A)</source> + <translation>Launch (A)</translation> + </message> + <message> + <source>Launch (B)</source> + <translation>Launch (B)</translation> + </message> + <message> + <source>Launch (C)</source> + <translation>Launch (C)</translation> + </message> + <message> + <source>Launch (D)</source> + <translation>Launch (D)</translation> + </message> + <message> + <source>Launch (E)</source> + <translation>Launch (E)</translation> + </message> + <message> + <source>Launch (F)</source> + <translation>Launch (F)</translation> + </message> + <message> + <source>Monitor Brightness Up</source> + <translation>افزایش درخشش نمایشگر</translation> + </message> + <message> + <source>Monitor Brightness Down</source> + <translation>Monitor Brightness Down</translation> + </message> + <message> + <source>Keyboard Light On/Off</source> + <translation>نور صفحهکلید (روشن/خاموش)</translation> + </message> + <message> + <source>Keyboard Brightness Up</source> + <translation>افزایش درخشش صفحهکلید</translation> + </message> + <message> + <source>Keyboard Brightness Down</source> + <translation>کاهش درخشش صفحهکلید</translation> + </message> + <message> + <source>Power Off</source> + <translation>قطع برق</translation> + </message> + <message> + <source>Wake Up</source> + <translation>بیدار شدن</translation> + </message> + <message> + <source>Eject</source> + <translation>بیرون آوردن</translation> + </message> + <message> + <source>Screensaver</source> + <translation>محافظ صفحه</translation> + </message> + <message> + <source>WWW</source> + <translation>WWW</translation> + </message> + <message> + <source>Sleep</source> + <translation>خواب</translation> + </message> + <message> + <source>LightBulb</source> + <translation>لامپ روشنایی</translation> + </message> + <message> + <source>Shop</source> + <translation>فروشگاه</translation> + </message> + <message> + <source>History</source> + <translation>تاریخ</translation> + </message> + <message> + <source>Add Favorite</source> + <translation>اضافه کردن علایق</translation> + </message> + <message> + <source>Hot Links</source> + <translation>پیوندهای داغ</translation> + </message> + <message> + <source>Adjust Brightness</source> + <translation>تنظیم درخشندگی</translation> + </message> + <message> + <source>Finance</source> + <translation>مالی</translation> + </message> + <message> + <source>Community</source> + <translation>جامعه</translation> + </message> + <message> + <source>Audio Rewind</source> + <translation>برگرداندن صدا</translation> + </message> + <message> + <source>Back Forward</source> + <translation>رو به عقب</translation> + </message> + <message> + <source>Application Left</source> + <translation>چپ برنامه</translation> + </message> + <message> + <source>Application Right</source> + <translation>راست برنامه</translation> + </message> + <message> + <source>Book</source> + <translation>کتاب</translation> + </message> + <message> + <source>CD</source> + <translation>سیدی</translation> + </message> + <message> + <source>Calculator</source> + <translation>ماشینحساب</translation> + </message> + <message> + <source>Clear</source> + <translation>پاک کردن</translation> + </message> + <message> + <source>Clear Grab</source> + <translation>پاک کردن قلاب</translation> + </message> + <message> + <source>Close</source> + <translation>بستن</translation> + </message> + <message> + <source>Copy</source> + <translation>کپی</translation> + </message> + <message> + <source>Cut</source> + <translation>برش</translation> + </message> + <message> + <source>Display</source> + <translation>نمایش</translation> + </message> + <message> + <source>DOS</source> + <translation>DOS</translation> + </message> + <message> + <source>Documents</source> + <translation>اسناد</translation> + </message> + <message> + <source>Spreadsheet</source> + <translation>صفحهگسترده</translation> + </message> + <message> + <source>Browser</source> + <translation>مرورگر</translation> + </message> + <message> + <source>Game</source> + <translation>بازی</translation> + </message> + <message> + <source>Go</source> + <translation>برو</translation> + </message> + <message> + <source>iTouch</source> + <translation>iTouch</translation> + </message> + <message> + <source>Logoff</source> + <translation>خروج</translation> + </message> + <message> + <source>Market</source> + <translation>بازار</translation> + </message> + <message> + <source>Meeting</source> + <translation>ملاقات</translation> + </message> + <message> + <source>Keyboard Menu</source> + <translation>منوی صفحهکلید</translation> + </message> + <message> + <source>Menu PB</source> + <translation>Menu PB</translation> + </message> + <message> + <source>My Sites</source> + <translation>سایتهای من</translation> + </message> + <message> + <source>News</source> + <translation>اخبار</translation> + </message> + <message> + <source>Home Office</source> + <translation>دفتر کار خانگی</translation> + </message> + <message> + <source>Option</source> + <translation>تنظیمات</translation> + </message> + <message> + <source>Paste</source> + <translation>چسباندن</translation> + </message> + <message> + <source>Phone</source> + <translation>تلفن</translation> + </message> + <message> + <source>Reply</source> + <translation>پاسخ</translation> + </message> + <message> + <source>Reload</source> + <translation>بارگذاری مجدد</translation> + </message> + <message> + <source>Rotate Windows</source> + <translation>چرخاندن پنجره</translation> + </message> + <message> + <source>Rotation PB</source> + <translation>چرخش PB</translation> + </message> + <message> + <source>Rotation KB</source> + <translation>چرخش KB</translation> + </message> + <message> + <source>Save</source> + <translation>ذخیره</translation> + </message> + <message> + <source>Send</source> + <translation>ارسال</translation> + </message> + <message> + <source>Spellchecker</source> + <translation>چککنندهٔ املا</translation> + </message> + <message> + <source>Split Screen</source> + <translation>تقسیم صفحه</translation> + </message> + <message> + <source>Support</source> + <translation>پشتیبانی</translation> + </message> + <message> + <source>Task Panel</source> + <translation>صفحهٔ وظیفه</translation> + </message> + <message> + <source>Terminal</source> + <translation>ترمینال</translation> + </message> + <message> + <source>Tools</source> + <translation>ابزار</translation> + </message> + <message> + <source>Travel</source> + <translation>سفر</translation> + </message> + <message> + <source>Video</source> + <translation>ویدئو</translation> + </message> + <message> + <source>Word Processor</source> + <translation>پردازشگر متن</translation> + </message> + <message> + <source>XFer</source> + <translation>XFer</translation> + </message> + <message> + <source>Zoom In</source> + <translation>بزرگنمایی</translation> + </message> + <message> + <source>Zoom Out</source> + <translation>کوچکنمایی</translation> + </message> + <message> + <source>Away</source> + <translation>دور</translation> + </message> + <message> + <source>Messenger</source> + <translation>پیامرسان</translation> + </message> + <message> + <source>WebCam</source> + <translation>وبکم</translation> + </message> + <message> + <source>Mail Forward</source> + <translation>دوباره فرستادن نامه</translation> + </message> + <message> + <source>Pictures</source> + <translation>عکسها</translation> + </message> + <message> + <source>Music</source> + <translation>موسیقی</translation> + </message> + <message> + <source>Battery</source> + <translation>باتری</translation> + </message> + <message> + <source>Bluetooth</source> + <translation>بلوتوث</translation> + </message> + <message> + <source>Wireless</source> + <translation>وایرلس</translation> + </message> + <message> + <source>Ultra Wide Band</source> + <translation>باند فوق پهن</translation> + </message> + <message> + <source>Audio Forward</source> + <translation>صدا - جلوبردن</translation> + </message> + <message> + <source>Audio Repeat</source> + <translation>تکرار صدا</translation> + </message> + <message> + <source>Audio Random Play</source> + <translation>صدا - اجرای تصادفی</translation> + </message> + <message> + <source>Subtitle</source> + <translation>زیرنویس</translation> + </message> + <message> + <source>Audio Cycle Track</source> + <translation>صدا - سیکل قطعه</translation> + </message> + <message> + <source>Time</source> + <translation>زمان</translation> + </message> + <message> + <source>Select</source> + <translation>انتخاب</translation> + </message> + <message> + <source>View</source> + <translation>نمایش</translation> + </message> + <message> + <source>Top Menu</source> + <translation>منوی بالا</translation> + </message> + <message> + <source>Suspend</source> + <translation>انجماد</translation> + </message> + <message> + <source>Hibernate</source> + <translation>خواب</translation> + </message> + <message> + <source>Print Screen</source> + <translation>چاپ کردن صفحه</translation> + </message> + <message> + <source>Page Up</source> + <translation>صفحه به بالا</translation> + </message> + <message> + <source>Page Down</source> + <translation>صفحه به پایین</translation> + </message> + <message> + <source>Caps Lock</source> + <translation>CapsLock</translation> + </message> + <message> + <source>Num Lock</source> + <translation>Num Lock</translation> + </message> + <message> + <source>Number Lock</source> + <translation>Number Lock</translation> + </message> + <message> + <source>Scroll Lock</source> + <translation>Scroll Lock</translation> + </message> + <message> + <source>Insert</source> + <translation>درج</translation> + </message> + <message> + <source>Delete</source> + <translation>حذف</translation> + </message> + <message> + <source>Escape</source> + <translation>Escape</translation> + </message> + <message> + <source>System Request</source> + <translation>درخواست سیستم</translation> + </message> + <message> + <source>Yes</source> + <translation>بله</translation> + </message> + <message> + <source>No</source> + <translation>نه</translation> + </message> + <message> + <source>Context1</source> + <translation>زمینهٔ ۱</translation> + </message> + <message> + <source>Context2</source> + <translation>زمینهٔ ۲</translation> + </message> + <message> + <source>Context3</source> + <translation>زمینهٔ ۳</translation> + </message> + <message> + <source>Context4</source> + <translation>زمینهٔ ۴</translation> + </message> + <message> + <source>Call</source> + <extracomment>Button to start a call (note: a separate button is used to end the call)</extracomment> + <translation>فراخوانی</translation> + </message> + <message> + <source>Hangup</source> + <extracomment>Button to end a call (note: a separate button is used to start the call)</extracomment> + <translation>هنگاپ</translation> + </message> + <message> + <source>Toggle Call/Hangup</source> + <extracomment>Button that will hang up if we're in call, or make a call if we're not.</extracomment> + <translation>تغییر وضعیت (فراخوانی/هنگاپ)</translation> + </message> + <message> + <source>Flip</source> + <translation>تلنگر</translation> + </message> + <message> + <source>Voice Dial</source> + <extracomment>Button to trigger voice dialing</extracomment> + <translation>شمارهگیری صوتی</translation> + </message> + <message> + <source>Last Number Redial</source> + <extracomment>Button to redial the last number called</extracomment> + <translation>شمارهگیری مجدد آخرین شماره</translation> + </message> + <message> + <source>Camera Shutter</source> + <extracomment>Button to trigger the camera shutter (take a picture)</extracomment> + <translation>شاتر دوربین</translation> + </message> + <message> + <source>Camera Focus</source> + <extracomment>Button to focus the camera</extracomment> + <translation>زوم دوربین</translation> + </message> + <message> + <source>Kanji</source> + <translation>Kanji</translation> + </message> + <message> + <source>Muhenkan</source> + <translation>Muhenkan</translation> + </message> + <message> + <source>Henkan</source> + <translation>Henkan</translation> + </message> + <message> + <source>Romaji</source> + <translation>Romaji</translation> + </message> + <message> + <source>Hiragana</source> + <translation>Hiragana</translation> + </message> + <message> + <source>Katakana</source> + <translation>Katakana</translation> + </message> + <message> + <source>Hiragana Katakana</source> + <translation>Hiragana Katakana</translation> + </message> + <message> + <source>Zenkaku</source> + <translation>Zenkaku</translation> + </message> + <message> + <source>Hankaku</source> + <translation>Hankaku</translation> + </message> + <message> + <source>Zenkaku Hankaku</source> + <translation>Zenkaku Hankaku</translation> + </message> + <message> + <source>Touroku</source> + <translation>Touroku</translation> + </message> + <message> + <source>Massyo</source> + <translation>Massyo</translation> + </message> + <message> + <source>Kana Lock</source> + <translation>Kana Lock</translation> + </message> + <message> + <source>Kana Shift</source> + <translation>Kana Shift</translation> + </message> + <message> + <source>Eisu Shift</source> + <translation>Eisu Shift</translation> + </message> + <message> + <source>Eisu toggle</source> + <translation>Eisu toggle</translation> + </message> + <message> + <source>Code input</source> + <translation>Code input</translation> + </message> + <message> + <source>Multiple Candidate</source> + <translation>Multiple Candidate</translation> + </message> + <message> + <source>Previous Candidate</source> + <translation>Previous Candidate</translation> + </message> + <message> + <source>Hangul</source> + <translation>Hangul</translation> + </message> + <message> + <source>Hangul Start</source> + <translation>شروع Hangul</translation> + </message> + <message> + <source>Hangul End</source> + <translation>پایان Hangul</translation> + </message> + <message> + <source>Hangul Hanja</source> + <translation>Hangul Hanja</translation> + </message> + <message> + <source>Hangul Jamo</source> + <translation>Hangul Jamo</translation> + </message> + <message> + <source>Hangul Romaja</source> + <translation>Hangul Romaja</translation> + </message> + <message> + <source>Hangul Jeonja</source> + <translation>Hangul Jeonja</translation> + </message> + <message> + <source>Hangul Banja</source> + <translation>Hangul Banja</translation> + </message> + <message> + <source>Hangul PreHanja</source> + <translation>Hangul PreHanja</translation> + </message> + <message> + <source>Hangul PostHanja</source> + <translation>Hangul PostHanja</translation> + </message> + <message> + <source>Hangul Special</source> + <translation>Hangul Special</translation> + </message> + <message> + <source>Ctrl</source> + <translation>Ctrl</translation> + </message> + <message> + <source>Shift</source> + <translation>Shift</translation> + </message> + <message> + <source>Alt</source> + <translation>Alt</translation> + </message> + <message> + <source>Meta</source> + <translation>Meta</translation> + </message> + <message> + <source>+</source> + <translation>+</translation> + </message> + <message> + <source>F%1</source> + <translation>F%1</translation> + </message> +</context> +<context> + <name>QSlider</name> + <message> + <source>Page left</source> + <translation>صفحه به چپ</translation> + </message> + <message> + <source>Page up</source> + <translation>صفحه به بالا</translation> + </message> + <message> + <source>Position</source> + <translation>موقعیت</translation> + </message> + <message> + <source>Page right</source> + <translation>صفحه به راست</translation> + </message> + <message> + <source>Page down</source> + <translation>صفحه به پایین</translation> + </message> +</context> +<context> + <name>QSocks5SocketEngine</name> + <message> + <source>Connection to proxy refused</source> + <translation>اتصال به پروکسی پذیرفته نشد</translation> + </message> + <message> + <source>Connection to proxy closed prematurely</source> + <translation>اتصال به پروکسی نابهنگام بسته شد</translation> + </message> + <message> + <source>Proxy host not found</source> + <translation>میزبان پروکسی پیدا نشد</translation> + </message> + <message> + <source>Connection to proxy timed out</source> + <translation>اتصال به پروکسی با وقفهٔ زمانی روبهرو شد</translation> + </message> + <message> + <source>Proxy authentication failed</source> + <translation>اعتبارسنجی ناموفق پروکسی</translation> + </message> + <message> + <source>Proxy authentication failed: %1</source> + <translation>اعتبارسنجی ناموفق پروکسی: %1</translation> + </message> + <message> + <source>SOCKS version 5 protocol error</source> + <translation>خطای پروتکل سوکت نسخهٔ ۵</translation> + </message> + <message> + <source>General SOCKSv5 server failure</source> + <translation>خرابی عمومی سرور SOCKSv5</translation> + </message> + <message> + <source>Connection not allowed by SOCKSv5 server</source> + <translation>اتصال بهوسیلهٔ سرور SOCKSv5 مجاز نیست</translation> + </message> + <message> + <source>TTL expired</source> + <translation>اTTL منقضی شده است</translation> + </message> + <message> + <source>SOCKSv5 command not supported</source> + <translation>دستور SOCKSv5 پشتیبانی نشده است</translation> + </message> + <message> + <source>Address type not supported</source> + <translation>نوع آدرس پشتیبانی نشده است</translation> + </message> + <message> + <source>Unknown SOCKSv5 proxy error code 0x%1</source> + <translation>کد 0x%1 خطای ناشناختهٔ پروکسی SOCKSv5</translation> + </message> + <message> + <source>Network operation timed out</source> + <translation>عملیات شبکه با وقفهٔ زمانی مواجه شد</translation> + </message> +</context> +<context> + <name>QSoftKeyManager</name> + <message> + <source>Ok</source> + <translation>تأیید</translation> + </message> + <message> + <source>Select</source> + <translation>انتخاب</translation> + </message> + <message> + <source>Done</source> + <translation>انجام شد</translation> + </message> + <message> + <source>Options</source> + <translation>تنظیمات</translation> + </message> + <message> + <source>Cancel</source> + <translation>لغو</translation> + </message> + <message> + <source>Exit</source> + <translation>خروج</translation> + </message> +</context> +<context> + <name>QSpinBox</name> + <message> + <source>More</source> + <translation>بیشتر</translation> + </message> + <message> + <source>Less</source> + <translation>کمتر</translation> + </message> +</context> +<context> + <name>QSql</name> + <message> + <source>Delete</source> + <translation>حذف</translation> + </message> + <message> + <source>Delete this record?</source> + <translation>این رکورد حذف شود؟</translation> + </message> + <message> + <source>Yes</source> + <translation>بله</translation> + </message> + <message> + <source>No</source> + <translation>نه</translation> + </message> + <message> + <source>Insert</source> + <translation>درج</translation> + </message> + <message> + <source>Update</source> + <translation>بهروزرسانی</translation> + </message> + <message> + <source>Save edits?</source> + <translation>تغییرات ذخیره شوند؟</translation> + </message> + <message> + <source>Cancel</source> + <translation>لغو</translation> + </message> + <message> + <source>Confirm</source> + <translation>تأیید</translation> + </message> + <message> + <source>Cancel your edits?</source> + <translation>تغییرات خود را لغو میکنید؟</translation> + </message> +</context> +<context> + <name>QSslSocket</name> + <message> + <source>No error</source> + <translation>خطا وجود ندارد</translation> + </message> + <message> + <source>The issuer certificate could not be found</source> + <translation>گواهینامهٔ درخواستکننده پیدا نمیشود</translation> + </message> + <message> + <source>The certificate signature could not be decrypted</source> + <translation>نمیتوان امضای گواهینامه را رمزگشایی نمود</translation> + </message> + <message> + <source>The public key in the certificate could not be read</source> + <translation>کلید عمومی تأییدیه خوانده نمیشود</translation> + </message> + <message> + <source>The signature of the certificate is invalid</source> + <translation>امضای گواهینامه نامعتبر است</translation> + </message> + <message> + <source>The certificate is not yet valid</source> + <translation>گواهینامه هنوز معتبر نیست</translation> + </message> + <message> + <source>The certificate has expired</source> + <translation>گواهینامه باطل شده است</translation> + </message> + <message> + <source>The certificate's notBefore field contains an invalid time</source> + <translation>رشتهٔ notBefore گواهینامه شامل یک آیتم نامعتبر است</translation> + </message> + <message> + <source>The certificate's notAfter field contains an invalid time</source> + <translation>رشتهٔ notAfter گواهینامه شامل یک آیتم نامعتبر است</translation> + </message> + <message> + <source>The certificate is self-signed, and untrusted</source> + <translation>گواهینامه، خود-امضا و غیرقابل اعتماد است</translation> + </message> + <message> + <source>The root certificate of the certificate chain is self-signed, and untrusted</source> + <translation>گواهینامهٔ ریشه در زنجیرهٔ گواهینامهها خود-امضا و غیرقابل اعتماد است</translation> + </message> + <message> + <source>The issuer certificate of a locally looked up certificate could not be found</source> + <translation>گواهینامهٔ درخواستکنندهٔ یک گواهینامهٔ جستجو شدهٔ محلی، پیدا نمیشود</translation> + </message> + <message> + <source>No certificates could be verified</source> + <translation>هیچ گواهینامهای قابل تأیید نیست</translation> + </message> + <message> + <source>One of the CA certificates is invalid</source> + <translation>یکی از گواهینامههای CA نامعتبر است</translation> + </message> + <message> + <source>The basicConstraints path length parameter has been exceeded</source> + <translation>پارامتر طول مسیر basicConstraints از حد تجاوز کرده است</translation> + </message> + <message> + <source>The supplied certificate is unsuitable for this purpose</source> + <translation>تأییدیهٔ تهیهشده برای این هدف نامناسب است</translation> + </message> + <message> + <source>The root CA certificate is not trusted for this purpose</source> + <translation>تأییدیهٔ ریشهٔ CA برای این هدف غیرقابلاطمینان است</translation> + </message> + <message> + <source>The root CA certificate is marked to reject the specified purpose</source> + <translation>تأییدیهٔ ریشهٔ CA برای رد هدف مشخص شدهای مارک شده است</translation> + </message> + <message> + <source>The current candidate issuer certificate was rejected because its subject name did not match the issuer name of the current certificate</source> + <translation>شمارهٔ تأییدیهٔ داوطلب جاری پذیرفته نشد زیرا موضوع نام آن با شمارهٔ نام تأییدیهٔ جاری همخوانی ندارد</translation> + </message> + <message> + <source>The current candidate issuer certificate was rejected because its issuer name and serial number was present and did not match the authority key identifier of the current certificate</source> + <translation>شمارهٔ تأییدیهٔ داوطلب جاری پذیرفته نشد زیرا شمارهٔ نام و شمارهٔ سریال ارائه شده با کلید مجوز تأییدیهٔ جاری همخوانی ندارد</translation> + </message> + <message> + <source>The peer did not present any certificate</source> + <translation>جفت تأییدیهای ارائه نداده است</translation> + </message> + <message> + <source>The host name did not match any of the valid hosts for this certificate</source> + <translation>نام میزبان با نام هیچ یک از میزبانهای معتبر برای این تأییدیه همخوانی ندارد</translation> + </message> + <message> + <source>Unknown error</source> + <translation>خطای ناشناخته</translation> + </message> + <message> + <source>Error creating SSL context (%1)</source> + <translation>خطای ایجاد زمینهٔ SSL (%1)</translation> + </message> + <message> + <source>Invalid or empty cipher list (%1)</source> + <translation>لیست رمز تهی یا نامعتبر (%1)</translation> + </message> + <message> + <source>Cannot provide a certificate with no key, %1</source> + <translation>نمیتوان بدون کلید یک تأییدیه تهیه کرد، %1</translation> + </message> + <message> + <source>Error loading local certificate, %1</source> + <translation>خطای بارگذاری تأییدیهٔ محلی، %1</translation> + </message> + <message> + <source>Error loading private key, %1</source> + <translation>خطای بارگذاری کلید اختصاصی، %1</translation> + </message> + <message> + <source>Private key does not certify public key, %1</source> + <translation>کلید اختصاصی کلید عمومی را تأیید نمیکند، %1</translation> + </message> + <message> + <source>Error creating SSL session, %1</source> + <translation>خطای ایجاد جلسهٔ SSL %1</translation> + </message> + <message> + <source>Error creating SSL session: %1</source> + <translation>خطای ایجاد جلسهٔ SSL: %1</translation> + </message> + <message> + <source>Unable to write data: %1</source> + <translation>نمیتوان روی داده نوشت: %1</translation> + </message> + <message> + <source>Unable to decrypt data: %1</source> + <translation>نمیتوان داده را رمزگشایی کرد: %1</translation> + </message> + <message> + <source>Error while reading: %1</source> + <translation>خطا در هنگام خواندن: %1</translation> + </message> + <message> + <source>Error during SSL handshake: %1</source> + <translation>خطا در هنگام دستدهی SSL: %1</translation> + </message> + <message> + <source>The peer certificate is blacklisted</source> + <translation>گواهینامهٔ جفت در لیست سیاه قرار دارد</translation> + </message> +</context> +<context> + <name>QStateMachine</name> + <message> + <source>Missing initial state in compound state '%1'</source> + <translation>حالت مقداردهی گمشده در حالت ترکیب «%1»</translation> + </message> + <message> + <source>Missing default state in history state '%1'</source> + <translation>حالت پیشفرض گمشده در حالت تاریخ «%1»</translation> + </message> + <message> + <source>No common ancestor for targets and source of transition from state '%1'</source> + <translation>فاقد نیای مشترک برای اهداف و منابع انتقالی از حالت «%1»</translation> + </message> + <message> + <source>Unknown error</source> + <translation>خطای ناشناخته</translation> + </message> +</context> +<context> + <name>QSystemSemaphore</name> + <message> + <source>%1: permission denied</source> + <translation>%1: حق دسترسی وجود ندارد</translation> + </message> + <message> + <source>%1: already exists</source> + <translation>%1: هماکنون موجود است</translation> + </message> + <message> + <source>%1: does not exist</source> + <translation>%1: وجود ندارد</translation> + </message> + <message> + <source>%1: out of resources</source> + <translation>%1: خارج از منابع</translation> + </message> + <message> + <source>%1: unknown error %2</source> + <translation>%1: خطای ناشناخته %2</translation> + </message> +</context> +<context> + <name>QTDSDriver</name> + <message> + <source>Unable to open connection</source> + <translation>نمیتوان اتصال را برقرار نمود</translation> + </message> + <message> + <source>Unable to use database</source> + <translation>نمیتوان از پایگاه داده استفاده کرد</translation> + </message> +</context> +<context> + <name>QTabBar</name> + <message> + <source>Scroll Left</source> + <translation>لغزش به چپ</translation> + </message> + <message> + <source>Scroll Right</source> + <translation>لغزش به راست</translation> + </message> +</context> +<context> + <name>QTcpServer</name> + <message> + <source>Operation on socket is not supported</source> + <translation>عملیات روی سوکت پشتیبانی نمیشود</translation> + </message> +</context> +<context> + <name>QTextControl</name> + <message> + <source>&Undo</source> + <translation>&خنثیسازی</translation> + </message> + <message> + <source>&Redo</source> + <translation>&بازانجام</translation> + </message> + <message> + <source>Cu&t</source> + <translation>ب&ریدن</translation> + </message> + <message> + <source>&Copy</source> + <translation>&کپی</translation> + </message> + <message> + <source>Copy &Link Location</source> + <translation>کپی و &پیوند دادن مکان</translation> + </message> + <message> + <source>&Paste</source> + <translation>&چسباندن</translation> + </message> + <message> + <source>Delete</source> + <translation>حذف</translation> + </message> + <message> + <source>Select All</source> + <translation>انتخاب همه</translation> + </message> +</context> +<context> + <name>QToolButton</name> + <message> + <source>Press</source> + <translation>فشار دادن</translation> + </message> + <message> + <source>Open</source> + <translation>باز کردن</translation> + </message> +</context> +<context> + <name>QUdpSocket</name> + <message> + <source>This platform does not support IPv6</source> + <translation>این پلتفرم IPv6 را پشتیبانی نمیکند</translation> + </message> +</context> +<context> + <name>QUndoGroup</name> + <message> + <source>Undo</source> + <translation>خنثیسازی</translation> + </message> + <message> + <source>Redo</source> + <translation>بازانجام</translation> + </message> +</context> +<context> + <name>QUndoModel</name> + <message> + <source><empty></source> + <translation><خالی></translation> + </message> +</context> +<context> + <name>QUndoStack</name> + <message> + <source>Undo</source> + <translation>خنثیسازی</translation> + </message> + <message> + <source>Redo</source> + <translation>بازانجام</translation> + </message> +</context> +<context> + <name>QUnicodeControlCharacterMenu</name> + <message> + <source>LRM Left-to-right mark</source> + <translation>LRM نشانهٔ چپ-به-راست</translation> + </message> + <message> + <source>RLM Right-to-left mark</source> + <translation>RLM نشانهٔ راست-به-چپ</translation> + </message> + <message> + <source>ZWJ Zero width joiner</source> + <translation>ZWJ متصلکننده با عرض صفر</translation> + </message> + <message> + <source>ZWNJ Zero width non-joiner</source> + <translation>ZWNJ فاصلهٔ غیرچسبان بدون عرض</translation> + </message> + <message> + <source>ZWSP Zero width space</source> + <translation>ZWSP فاصلهٔ بدون عرض</translation> + </message> + <message> + <source>LRE Start of left-to-right embedding</source> + <translation>LRE شروع حالت تعبیهشدهٔ چپ-به-راست</translation> + </message> + <message> + <source>RLE Start of right-to-left embedding</source> + <translation>RLE شروع حالت تعبیهشدهٔ راست-به-چپ</translation> + </message> + <message> + <source>LRO Start of left-to-right override</source> + <translation>LRO شروع رویهمگذاری چپ-به-راست</translation> + </message> + <message> + <source>RLO Start of right-to-left override</source> + <translation>RLO شروع رویهمگذاری راست-به-چپ</translation> + </message> + <message> + <source>PDF Pop directional formatting</source> + <translation>PDF قالببندی Pop directional</translation> + </message> + <message> + <source>Insert Unicode control character</source> + <translation>درج نویسهٔ کنترلی یونیکد</translation> + </message> +</context> +<context> + <name>QWebFrame</name> + <message> + <source>Request cancelled</source> + <translation>درخواست لغو شد</translation> + </message> + <message> + <source>Request blocked</source> + <translation>درخواست بلوکه شد</translation> + </message> + <message> + <source>Cannot show URL</source> + <translation>نمیتوان URL را نمایش داد</translation> + </message> + <message> + <source>Frame load interrupted by policy change</source> + <translation>بارگذاری فریم با تغییر سیاست دچار وقفه شد</translation> + </message> + <message> + <source>Cannot show mimetype</source> + <translation>نمیتوان mimetype را نمایش داد</translation> + </message> + <message> + <source>File does not exist</source> + <translation>پرونده وجود ندارد</translation> + </message> +</context> +<context> + <name>QWebPage</name> + <message> + <source>Redirection limit reached</source> + <translation>رسیدن به محدودیت تعیین مسیر</translation> + </message> + <message> + <source>Bad HTTP request</source> + <translation>درخواست HTTP ناهنجار</translation> + </message> + <message numerus="yes"> + <source>%n file(s)</source> + <comment>number of chosen file</comment> + <translation> + <numerusform>%n پرونده</numerusform> + </translation> + </message> + <message> + <source>Submit</source> + <comment>default label for Submit buttons in forms on web pages</comment> + <translation>ارسال</translation> + </message> + <message> + <source>Submit</source> + <comment>Submit (input element) alt text for <input> elements with no alt, title, or value</comment> + <translation>ارسال</translation> + </message> + <message> + <source>Reset</source> + <comment>default label for Reset buttons in forms on web pages</comment> + <translation>بازتنظیم</translation> + </message> + <message> + <source>This is a searchable index. Enter search keywords: </source> + <comment>text that appears at the start of nearly-obsolete web pages in the form of a 'searchable index'</comment> + <translation>این یک شاخص قابل جستجو است. کلیدواژههای جستجو را وارد کنید:</translation> + </message> + <message> + <source>Choose File</source> + <comment>title for file button used in HTML forms</comment> + <translation>پرونده را انتخاب کنید</translation> + </message> + <message> + <source>No file selected</source> + <comment>text to display in file button used in HTML forms when no file is selected</comment> + <translation>پروندهای انتخاب نشد</translation> + </message> + <message> + <source>Open in New Window</source> + <comment>Open in New Window context menu item</comment> + <translation>بازکردن در پنجرهٔ جدید</translation> + </message> + <message> + <source>Save Link...</source> + <comment>Download Linked File context menu item</comment> + <translation>ذخیرهٔ پیوند...</translation> + </message> + <message> + <source>Copy Link</source> + <comment>Copy Link context menu item</comment> + <translation>کپی پیوند</translation> + </message> + <message> + <source>Open Image</source> + <comment>Open Image in New Window context menu item</comment> + <translation>بازکردن تصویر</translation> + </message> + <message> + <source>Save Image</source> + <comment>Download Image context menu item</comment> + <translation>ذخیرهٔ تصویر</translation> + </message> + <message> + <source>Copy Image</source> + <comment>Copy Link context menu item</comment> + <translation>کپی تصویر</translation> + </message> + <message> + <source>Open Frame</source> + <comment>Open Frame in New Window context menu item</comment> + <translation>بازکردن فریم</translation> + </message> + <message> + <source>Copy</source> + <comment>Copy context menu item</comment> + <translation>کپی</translation> + </message> + <message> + <source>Go Back</source> + <comment>Back context menu item</comment> + <translation>عقبگرد</translation> + </message> + <message> + <source>Go Forward</source> + <comment>Forward context menu item</comment> + <translation>جلوگرد</translation> + </message> + <message> + <source>Stop</source> + <comment>Stop context menu item</comment> + <translation>توقف</translation> + </message> + <message> + <source>Reload</source> + <comment>Reload context menu item</comment> + <translation>بارگذاری مجدد</translation> + </message> + <message> + <source>Cut</source> + <comment>Cut context menu item</comment> + <translation>برش</translation> + </message> + <message> + <source>Paste</source> + <comment>Paste context menu item</comment> + <translation>چسباندن</translation> + </message> + <message> + <source>No Guesses Found</source> + <comment>No Guesses Found context menu item</comment> + <translation>تخمینی پیدا نشد</translation> + </message> + <message> + <source>Ignore</source> + <comment>Ignore Spelling context menu item</comment> + <translation>نادیده گرفتن</translation> + </message> + <message> + <source>Add To Dictionary</source> + <comment>Learn Spelling context menu item</comment> + <translation>اضافهکردن به دیکشنری</translation> + </message> + <message> + <source>Search The Web</source> + <comment>Search The Web context menu item</comment> + <translation>جستجوی وب</translation> + </message> + <message> + <source>Look Up In Dictionary</source> + <comment>Look Up in Dictionary context menu item</comment> + <translation>جستجو در دیکشنری</translation> + </message> + <message> + <source>Open Link</source> + <comment>Open Link context menu item</comment> + <translation>بازکردن لینک</translation> + </message> + <message> + <source>Ignore</source> + <comment>Ignore Grammar context menu item</comment> + <translation>نادیده گرفتن</translation> + </message> + <message> + <source>Spelling</source> + <comment>Spelling and Grammar context sub-menu item</comment> + <translation>هجی کردن</translation> + </message> + <message> + <source>Show Spelling and Grammar</source> + <comment>menu item title</comment> + <translation>نمایش املا و گرامر</translation> + </message> + <message> + <source>Hide Spelling and Grammar</source> + <comment>menu item title</comment> + <translation>مخفیکردن املا و گرامر</translation> + </message> + <message> + <source>Check Spelling</source> + <comment>Check spelling context menu item</comment> + <translation>بررسی املا</translation> + </message> + <message> + <source>Check Spelling While Typing</source> + <comment>Check spelling while typing context menu item</comment> + <translation>بررسی املا هنگام نوشتن</translation> + </message> + <message> + <source>Check Grammar With Spelling</source> + <comment>Check grammar with spelling context menu item</comment> + <translation>بررسی گرامر در هنگام نوشتن</translation> + </message> + <message> + <source>Fonts</source> + <comment>Font context sub-menu item</comment> + <translation>قلمها</translation> + </message> + <message> + <source>Bold</source> + <comment>Bold context menu item</comment> + <translation>توپر</translation> + </message> + <message> + <source>Italic</source> + <comment>Italic context menu item</comment> + <translation>کج</translation> + </message> + <message> + <source>Underline</source> + <comment>Underline context menu item</comment> + <translation>زیرخطدار</translation> + </message> + <message> + <source>Outline</source> + <comment>Outline context menu item</comment> + <translation>خطوط پیرامونی</translation> + </message> + <message> + <source>Direction</source> + <comment>Writing direction context sub-menu item</comment> + <translation>جهت</translation> + </message> + <message> + <source>Text Direction</source> + <comment>Text direction context sub-menu item</comment> + <translation>جهت متن</translation> + </message> + <message> + <source>Default</source> + <comment>Default writing direction context menu item</comment> + <translation>پیشفرض</translation> + </message> + <message> + <source>Left to Right</source> + <comment>Left to Right context menu item</comment> + <translation>چپ به راست</translation> + </message> + <message> + <source>Right to Left</source> + <comment>Right to Left context menu item</comment> + <translation>راست به چپ</translation> + </message> + <message> + <source>Inspect</source> + <comment>Inspect Element context menu item</comment> + <translation>بررسیکردن</translation> + </message> + <message> + <source>No recent searches</source> + <comment>Label for only item in menu that appears when clicking on the search field image, when no searches have been performed</comment> + <translation>جستجویی انجام نشده</translation> + </message> + <message> + <source>Recent searches</source> + <comment>label for first item in the menu that appears when clicking on the search field image, used as embedded menu title</comment> + <translation>جستجوهای پیشین</translation> + </message> + <message> + <source>Clear recent searches</source> + <comment>menu item in Recent Searches menu that empties menu's contents</comment> + <translation>پاککردن جستجوهای پیشین</translation> + </message> + <message> + <source>Missing Plug-in</source> + <comment>Label text to be used when a plug-in is missing</comment> + <translation>افزونهٔ گمشده</translation> + </message> + <message> + <source>Unknown</source> + <comment>Unknown filesize FTP directory listing item</comment> + <translation>ناشناخته</translation> + </message> + <message> + <source>%1 (%2x%3 pixels)</source> + <comment>Title string for images</comment> + <translation>%1 (%2x%3 پیکسل)</translation> + </message> + <message> + <source>Loading...</source> + <comment>Media controller status message when the media is loading</comment> + <translation>بارگذاری...</translation> + </message> + <message> + <source>Live Broadcast</source> + <comment>Media controller status message when watching a live broadcast</comment> + <translation>پخش زنده</translation> + </message> + <message> + <source>Audio Element</source> + <comment>Media controller element</comment> + <translation>عنصر صوتی</translation> + </message> + <message> + <source>Video Element</source> + <comment>Media controller element</comment> + <translation>عنصر تصویری</translation> + </message> + <message> + <source>Mute Button</source> + <comment>Media controller element</comment> + <translation>دکمهٔ قطع صدا</translation> + </message> + <message> + <source>Unmute Button</source> + <comment>Media controller element</comment> + <translation>دکمهٔ وصل صدا</translation> + </message> + <message> + <source>Play Button</source> + <comment>Media controller element</comment> + <translation>دکمهٔ اجرا</translation> + </message> + <message> + <source>Pause Button</source> + <comment>Media controller element</comment> + <translation>دکمهٔ توقف</translation> + </message> + <message> + <source>Slider</source> + <comment>Media controller element</comment> + <translation>لغزنده</translation> + </message> + <message> + <source>Slider Thumb</source> + <comment>Media controller element</comment> + <translation>بندانگشتی لغزنده</translation> + </message> + <message> + <source>Rewind Button</source> + <comment>Media controller element</comment> + <translation>دکمهٔ پیچاندن</translation> + </message> + <message> + <source>Return to Real-time Button</source> + <comment>Media controller element</comment> + <translation>بازگشت به دکمهٔ زمان-واقعی</translation> + </message> + <message> + <source>Elapsed Time</source> + <comment>Media controller element</comment> + <translation>زمان صرف شده</translation> + </message> + <message> + <source>Remaining Time</source> + <comment>Media controller element</comment> + <translation>زمان باقیمانده</translation> + </message> + <message> + <source>Status Display</source> + <comment>Media controller element</comment> + <translation>نمایش وضعیت</translation> + </message> + <message> + <source>Fullscreen Button</source> + <comment>Media controller element</comment> + <translation>دکمهٔ تمامصفحه</translation> + </message> + <message> + <source>Seek Forward Button</source> + <comment>Media controller element</comment> + <translation>دکمهٔ لغزش رو به جلو</translation> + </message> + <message> + <source>Seek Back Button</source> + <comment>Media controller element</comment> + <translation>دکمهٔ لغزش رو به عقب</translation> + </message> + <message> + <source>Audio element playback controls and status display</source> + <comment>Media controller element</comment> + <translation>کنترلها و نمایش وضعیت پخش عنصر صوتی</translation> + </message> + <message> + <source>Video element playback controls and status display</source> + <comment>Media controller element</comment> + <translation>کنترلها و نمایش وضعیت پخش عنصر تصویری</translation> + </message> + <message> + <source>Mute audio tracks</source> + <comment>Media controller element</comment> + <translation>خاموشکردن قطعههای صوتی</translation> + </message> + <message> + <source>Unmute audio tracks</source> + <comment>Media controller element</comment> + <translation>روشنکردن قطعههای صوتی</translation> + </message> + <message> + <source>Begin playback</source> + <comment>Media controller element</comment> + <translation>شروع پخش</translation> + </message> + <message> + <source>Pause playback</source> + <comment>Media controller element</comment> + <translation>توقف پخش</translation> + </message> + <message> + <source>Movie time scrubber</source> + <comment>Media controller element</comment> + <translation>پاککنندهٔ زمان فیلم</translation> + </message> + <message> + <source>Movie time scrubber thumb</source> + <comment>Media controller element</comment> + <translation>بندانگشتی پاککنندهٔ زمان فیلم</translation> + </message> + <message> + <source>Rewind movie</source> + <comment>Media controller element</comment> + <translation> عقبگرد فیلم</translation> + </message> + <message> + <source>Return streaming movie to real-time</source> + <comment>Media controller element</comment> + <translation>بازگشت جریان فیلم به زمان-واقعی</translation> + </message> + <message> + <source>Current movie time</source> + <comment>Media controller element</comment> + <translation>زمان جاری فیلم</translation> + </message> + <message> + <source>Remaining movie time</source> + <comment>Media controller element</comment> + <translation>زمان باقیماندهٔ فیلم</translation> + </message> + <message> + <source>Current movie status</source> + <comment>Media controller element</comment> + <translation>وضعیت جاری فیلم</translation> + </message> + <message> + <source>Play movie in full-screen mode</source> + <comment>Media controller element</comment> + <translation>اجرای فیلم در حالت تمام صفحه</translation> + </message> + <message> + <source>Seek quickly back</source> + <comment>Media controller element</comment> + <translation>لغزش سریع رو به عقب</translation> + </message> + <message> + <source>Seek quickly forward</source> + <comment>Media controller element</comment> + <translation>لغزش سریع رو به جلو</translation> + </message> + <message> + <source>Indefinite time</source> + <comment>Media time description</comment> + <translation>زمان نامعلوم</translation> + </message> + <message> + <source>%1 days %2 hours %3 minutes %4 seconds</source> + <comment>Media time description</comment> + <translation>%1 روز %2 ساعت %3 دقیقه %4 ثانیه</translation> + </message> + <message> + <source>%1 hours %2 minutes %3 seconds</source> + <comment>Media time description</comment> + <translation>%1 ساعت %2 دقیقه %3 ثانیه</translation> + </message> + <message> + <source>%1 minutes %2 seconds</source> + <comment>Media time description</comment> + <translation>%1 دقیقه %2 ثانیه</translation> + </message> + <message> + <source>%1 seconds</source> + <comment>Media time description</comment> + <translation>%1 ثانیه</translation> + </message> + <message> + <source>Scroll here</source> + <translation>لغزش به اینجا</translation> + </message> + <message> + <source>Left edge</source> + <translation>یال چپ</translation> + </message> + <message> + <source>Top</source> + <translation>بالا</translation> + </message> + <message> + <source>Right edge</source> + <translation>یال راست</translation> + </message> + <message> + <source>Bottom</source> + <translation>کف</translation> + </message> + <message> + <source>Page left</source> + <translation>صفحه به چپ</translation> + </message> + <message> + <source>Page up</source> + <translation>صفحه به بالا</translation> + </message> + <message> + <source>Page right</source> + <translation>صفحه به راست</translation> + </message> + <message> + <source>Page down</source> + <translation>صفحه به پایین</translation> + </message> + <message> + <source>Scroll left</source> + <translation>لغزش به چپ</translation> + </message> + <message> + <source>Scroll up</source> + <translation>لغزش به بالا</translation> + </message> + <message> + <source>Scroll right</source> + <translation>لغزش به راست</translation> + </message> + <message> + <source>Scroll down</source> + <translation>لغزش به پایین</translation> + </message> + <message> + <source>JavaScript Alert - %1</source> + <translation>اخطار جاوااسکریپت - %1</translation> + </message> + <message> + <source>JavaScript Confirm - %1</source> + <translation>تأیید جاوااسکریپت - %1</translation> + </message> + <message> + <source>JavaScript Prompt - %1</source> + <translation>عکسالعمل جاوااسکریپت - %1</translation> + </message> + <message> + <source>JavaScript Problem - %1</source> + <translation>مشکل جاوااسکریپت - %1</translation> + </message> + <message> + <source>The script on this page appears to have a problem. Do you want to stop the script?</source> + <translation>به نظر میرسد اسکریپت در این صفحه مشکلی دارد. آیا مایل هستید اسکریپت را متوقف کنید؟</translation> + </message> + <message> + <source>Move the cursor to the next character</source> + <translation>نشانگر را به نویسهٔ بعدی حرکت بده</translation> + </message> + <message> + <source>Move the cursor to the previous character</source> + <translation>نشانگر را به نویسهٔ قبلی حرکت بده</translation> + </message> + <message> + <source>Move the cursor to the next word</source> + <translation>نشانگر را به کلمهٔ بعدی حرکت بده</translation> + </message> + <message> + <source>Move the cursor to the previous word</source> + <translation>نشانگر را به کلمهٔ قبلی حرکت بده</translation> + </message> + <message> + <source>Move the cursor to the next line</source> + <translation>نشانگر را به خط بعدی حرکت بده</translation> + </message> + <message> + <source>Move the cursor to the previous line</source> + <translation>نشانگر را به خط قبلی حرکت بده</translation> + </message> + <message> + <source>Move the cursor to the start of the line</source> + <translation>نشانگر را به شروع خط حرکت بده</translation> + </message> + <message> + <source>Move the cursor to the end of the line</source> + <translation>نشانگر را به پایان خط حرکت بده</translation> + </message> + <message> + <source>Move the cursor to the start of the block</source> + <translation>نشانگر را به شروع بلاک حرکت بده</translation> + </message> + <message> + <source>Move the cursor to the end of the block</source> + <translation>نشانگر را به پایان بلاک حرکت بده</translation> + </message> + <message> + <source>Move the cursor to the start of the document</source> + <translation>نشانگر را به شروع سند حرکت بده</translation> + </message> + <message> + <source>Move the cursor to the end of the document</source> + <translation>نشانگر را به پایان سند حرکت بده</translation> + </message> + <message> + <source>Select all</source> + <translation>انتخاب همه</translation> + </message> + <message> + <source>Select to the next character</source> + <translation>انتخاب کاراکتر بعدی</translation> + </message> + <message> + <source>Select to the previous character</source> + <translation>انتخاب کاراکتر قبلی</translation> + </message> + <message> + <source>Select to the next word</source> + <translation>انتخاب کلمهٔ بعدی</translation> + </message> + <message> + <source>Select to the previous word</source> + <translation>انتخاب کلمهٔ قبلی</translation> + </message> + <message> + <source>Select to the next line</source> + <translation>انتخاب خط بعدی</translation> + </message> + <message> + <source>Select to the previous line</source> + <translation>انتخاب خط قبلی</translation> + </message> + <message> + <source>Select to the start of the line</source> + <translation>انتخاب شروع خط</translation> + </message> + <message> + <source>Select to the end of the line</source> + <translation>انتخاب پایان خط</translation> + </message> + <message> + <source>Select to the start of the block</source> + <translation>انتخاب شروع بلاک</translation> + </message> + <message> + <source>Select to the end of the block</source> + <translation>انتخاب پایان بلاک</translation> + </message> + <message> + <source>Select to the start of the document</source> + <translation>انتخاب شروع سند</translation> + </message> + <message> + <source>Select to the end of the document</source> + <translation>انتخاب پایان سند</translation> + </message> + <message> + <source>Delete to the start of the word</source> + <translation>انتخاب شروع کلمه</translation> + </message> + <message> + <source>Delete to the end of the word</source> + <translation>انتخاب پایان کلمه</translation> + </message> + <message> + <source>Insert a new paragraph</source> + <translation>درج پاراگراف جدید</translation> + </message> + <message> + <source>Insert a new line</source> + <translation>درج خط جدید</translation> + </message> + <message> + <source>Paste and Match Style</source> + <translation>چسباندن و تطبیق سبک</translation> + </message> + <message> + <source>Remove formatting</source> + <translation>حذف قالببندی</translation> + </message> + <message> + <source>Strikethrough</source> + <translation>خطدار</translation> + </message> + <message> + <source>Subscript</source> + <translation>زیرنگاشت</translation> + </message> + <message> + <source>Superscript</source> + <translation>بالانگاشت</translation> + </message> + <message> + <source>Insert Bulleted List</source> + <translation>درج سیاههٔ نقطهدار</translation> + </message> + <message> + <source>Insert Numbered List</source> + <translation>درج سیاههٔ شمارهدار</translation> + </message> + <message> + <source>Indent</source> + <translation>تورفتگی</translation> + </message> + <message> + <source>Outdent</source> + <translation>بیرونزدگی</translation> + </message> + <message> + <source>Center</source> + <translation>مرکز</translation> + </message> + <message> + <source>Justify</source> + <translation>تراز از دو طرف</translation> + </message> + <message> + <source>Align Left</source> + <translation>ترازکردن از چپ</translation> + </message> + <message> + <source>Align Right</source> + <translation>ترازکردن از راست</translation> + </message> + <message> + <source>Web Inspector - %2</source> + <translation>بررسیکنندهٔ وب - %2</translation> + </message> +</context> +<context> + <name>QWhatsThisAction</name> + <message> + <source>What's This?</source> + <translation>این چیست؟</translation> + </message> +</context> +<context> + <name>QWidget</name> + <message> + <source>*</source> + <translation>*</translation> + </message> +</context> +<context> + <name>QWizard</name> + <message> + <source>Go Back</source> + <translation>برو عقب</translation> + </message> + <message> + <source>< &Back</source> + <translation>< &عقب</translation> + </message> + <message> + <source>Continue</source> + <translation>ادامه</translation> + </message> + <message> + <source>&Next</source> + <translation>بع&دی</translation> + </message> + <message> + <source>&Next ></source> + <translation>بع&دی ></translation> + </message> + <message> + <source>Commit</source> + <translation>ارسال</translation> + </message> + <message> + <source>Done</source> + <translation>انجام شد</translation> + </message> + <message> + <source>&Finish</source> + <translation>پایا&ن</translation> + </message> + <message> + <source>Cancel</source> + <translation>لغو</translation> + </message> + <message> + <source>Help</source> + <translation>کمک</translation> + </message> + <message> + <source>&Help</source> + <translation>&کمک</translation> + </message> +</context> +<context> + <name>QWorkspace</name> + <message> + <source>Close</source> + <translation>بستن</translation> + </message> + <message> + <source>Minimize</source> + <translation>کوچک کردن</translation> + </message> + <message> + <source>Restore Down</source> + <translation>بازیابی به پایین</translation> + </message> + <message> + <source>&Restore</source> + <translation>با&زیابی</translation> + </message> + <message> + <source>&Move</source> + <translation>&حرکت</translation> + </message> + <message> + <source>&Size</source> + <translation>&اندازه</translation> + </message> + <message> + <source>Mi&nimize</source> + <translation>کوچ&ک کردن</translation> + </message> + <message> + <source>Ma&ximize</source> + <translation>بزر&گ کردن</translation> + </message> + <message> + <source>&Close</source> + <translation>&بستن</translation> + </message> + <message> + <source>Stay on &Top</source> + <translation>بالاتر ب&ماند</translation> + </message> + <message> + <source>Sh&ade</source> + <translation>&سایه</translation> + </message> + <message> + <source>%1 - [%2]</source> + <translation>%1 ـ [%2]</translation> + </message> + <message> + <source>&Unshade</source> + <translation>بازنشانی &سایه</translation> + </message> +</context> +<context> + <name>QXml</name> + <message> + <source>no error occurred</source> + <translation>خطایی رخ نداد</translation> + </message> + <message> + <source>error triggered by consumer</source> + <translation>خطای تحریک شده بهوسیلهٔ مصرفکننده</translation> + </message> + <message> + <source>unexpected end of file</source> + <translation>انتهای نامنتظرهٔ پرونده</translation> + </message> + <message> + <source>more than one document type definition</source> + <translation>بیشتر از یک تعریف نوع سند</translation> + </message> + <message> + <source>error occurred while parsing element</source> + <translation>خطا در هنگام تحلیل عنصر رخ داد</translation> + </message> + <message> + <source>tag mismatch</source> + <translation>عدم تطابق نشانه</translation> + </message> + <message> + <source>error occurred while parsing content</source> + <translation>خطا در هنگام تحلیل محتوا رخ داد</translation> + </message> + <message> + <source>unexpected character</source> + <translation>نویسهٔ غیرمنتظرهٔ</translation> + </message> + <message> + <source>invalid name for processing instruction</source> + <translation>نام نامعتبر برای معرفی پردازش</translation> + </message> + <message> + <source>version expected while reading the XML declaration</source> + <translation>هنگام خواندن XML نسخه نیاز است</translation> + </message> + <message> + <source>wrong value for standalone declaration</source> + <translation>مقدار اشتباه برای بیان مستقل</translation> + </message> + <message> + <source>encoding declaration or standalone declaration expected while reading the XML declaration</source> + <translation>هنگام خواندن XML بیان کدگذاری یا بیان مستقل نیاز است</translation> + </message> + <message> + <source>standalone declaration expected while reading the XML declaration</source> + <translation>هنگام خواندن XML بیان مستقل نیاز است</translation> + </message> + <message> + <source>error occurred while parsing document type definition</source> + <translation>خطا در هنگام تحلیل نوع تعریف سند رخ داد</translation> + </message> + <message> + <source>letter is expected</source> + <translation>حرف مورد انتظار است</translation> + </message> + <message> + <source>error occurred while parsing comment</source> + <translation>خطا در هنگام تحلیل پیام رخ داد</translation> + </message> + <message> + <source>error occurred while parsing reference</source> + <translation>خطا در هنگام تحلیل مرجع رخ داد</translation> + </message> + <message> + <source>internal general entity reference not allowed in DTD</source> + <translation>موجودیت عمومی داخلی مرجع در DTD مجاز نیست</translation> + </message> + <message> + <source>external parsed general entity reference not allowed in attribute value</source> + <translation>موجودیت عمومی تجزیهشدهٔ خارجی مرجع در مقدار صفت مجاز نیست</translation> + </message> + <message> + <source>external parsed general entity reference not allowed in DTD</source> + <translation>موجودیت عمومی تجزیهشدهٔ خارجی مرجع در DTD مجاز نیست</translation> + </message> + <message> + <source>unparsed entity reference in wrong context</source> + <translation>موجودیت عمومی تجزیهنشدهٔ مرجع در زمینهٔ اشتباه</translation> + </message> + <message> + <source>recursive entities</source> + <translation>موجودیتهای بازگشتی</translation> + </message> + <message> + <source>error in the text declaration of an external entity</source> + <translation>خطا در بیان متنی یک موجودیت خارجی</translation> + </message> +</context> +<context> + <name>QXmlPatternistCLI</name> + <message> + <source>Warning in %1, at line %2, column %3: %4</source> + <translation>اخطار در %1 ،در خط %2 ، ستون %3: %4</translation> + </message> + <message> + <source>Warning in %1: %2</source> + <translation>اخطار در %1: %2</translation> + </message> + <message> + <source>Unknown location</source> + <translation>موقعیت ناشناخته</translation> + </message> + <message> + <source>Error %1 in %2, at line %3, column %4: %5</source> + <translation>خطای %1 در %2 ،در خط %3 ، ستون %4: %5</translation> + </message> + <message> + <source>Error %1 in %2: %3</source> + <translation>خطای %1 در %2: %3</translation> + </message> +</context> +<context> + <name>QXmlStream</name> + <message> + <source>Extra content at end of document.</source> + <translation>محتویات اضافه در انتهای سند.</translation> + </message> + <message> + <source>Invalid entity value.</source> + <translation>مقدار موجودیت نامعتبر.</translation> + </message> + <message> + <source>Invalid XML character.</source> + <translation>نویسهٔ نامعتبر XML.</translation> + </message> + <message> + <source>Sequence ']]>' not allowed in content.</source> + <translation>رشتهٔ «<[[» در محتوا مجاز نیست.</translation> + </message> + <message> + <source>Encountered incorrectly encoded content.</source> + <translation>رویارویی با محتوای کدگذاری شده بهشکل نادرست.</translation> + </message> + <message> + <source>Namespace prefix '%1' not declared</source> + <translation>پیشوند «%1» فضاینامی تعریف نشده است</translation> + </message> + <message> + <source>Illegal namespace declaration.</source> + <translation>بیان غیرمجاز فضاینامی.</translation> + </message> + <message> + <source>Attribute redefined.</source> + <translation>بازتعریف صفت.</translation> + </message> + <message> + <source>Unexpected character '%1' in public id literal.</source> + <translation>نویسهٔ غیرمنتظرهٔ «%1» در رشتهٔ id عمومی.</translation> + </message> + <message> + <source>Invalid XML version string.</source> + <translation>رشتهٔ نامعتبر نسخهٔ XML.</translation> + </message> + <message> + <source>Unsupported XML version.</source> + <translation>نسخهٔ پشتیبانی نشدهٔ XML.</translation> + </message> + <message> + <source>The standalone pseudo attribute must appear after the encoding.</source> + <translation>صفت مستقل کاذب باید بعد از کدگذاری ظاهر شود.</translation> + </message> + <message> + <source>%1 is an invalid encoding name.</source> + <translation>%1 یک نام کدگذاری نامعتبر است.</translation> + </message> + <message> + <source>Encoding %1 is unsupported</source> + <translation>کدگذاری %1 پشتیبانی نشده است</translation> + </message> + <message> + <source>Standalone accepts only yes or no.</source> + <translation>پذیرفتنهای مستقل فقط بله یا خیر.</translation> + </message> + <message> + <source>Invalid attribute in XML declaration.</source> + <translation>صفت نامعتبر در بیان XML.</translation> + </message> + <message> + <source>Premature end of document.</source> + <translation>پایان نابههنگام سند.</translation> + </message> + <message> + <source>Invalid document.</source> + <translation>سند نامعتبر.</translation> + </message> + <message> + <source>Expected </source> + <translation>مورد انتظار</translation> + </message> + <message> + <source>, but got '</source> + <translation>، اما دریافت شده: '</translation> + </message> + <message> + <source>Unexpected '</source> + <translation>نامنتظره '</translation> + </message> + <message> + <source>Expected character data.</source> + <translation>دادهٔ نویسه مورد انتظار است.</translation> + </message> + <message> + <source>Recursive entity detected.</source> + <translation>موجودیت بازگشتی پیدا شد.</translation> + </message> + <message> + <source>Start tag expected.</source> + <translation>نشانهٔ شروع مورد انتظار.</translation> + </message> + <message> + <source>NDATA in parameter entity declaration.</source> + <translation>NDATA در بیان موجودیت پارامتر.</translation> + </message> + <message> + <source>XML declaration not at start of document.</source> + <translation>بیان XML در ابتدای سند نیست.</translation> + </message> + <message> + <source>%1 is an invalid processing instruction name.</source> + <translation>%1 یک دستورالعمل پردازشی نامعتبر است.</translation> + </message> + <message> + <source>Invalid processing instruction name.</source> + <translation>دستورالعمل پردازشی نامعتبر.</translation> + </message> + <message> + <source>%1 is an invalid PUBLIC identifier.</source> + <translation>%1 یک شناسهٔ عمومی نامعتبر است.</translation> + </message> + <message> + <source>Invalid XML name.</source> + <translation>نام XML نامعتبر.</translation> + </message> + <message> + <source>Opening and ending tag mismatch.</source> + <translation>نشانهٔ شروع و پایان نامناسب.</translation> + </message> + <message> + <source>Entity '%1' not declared.</source> + <translation>موجودیت «%1» بیان نشده است.</translation> + </message> + <message> + <source>Reference to unparsed entity '%1'.</source> + <translation>ارجاع به موجودیت تحلیلنشده «%1».</translation> + </message> + <message> + <source>Reference to external entity '%1' in attribute value.</source> + <translatorcomment>ارجاع به موجودیت خارجی «%1» در مقدار صفت.</translatorcomment> + <translation></translation> + </message> + <message> + <source>Invalid character reference.</source> + <translation>ارجاع کاراکتر نامعتبر.</translation> + </message> +</context> +<context> + <name>QtXmlPatterns</name> + <message> + <source>%1 is an unsupported encoding.</source> + <translation>%1 یک کدگذاری پشتیبانی نشده است.</translation> + </message> + <message> + <source>%1 contains octets which are disallowed in the requested encoding %2.</source> + <translation>%1 شامل هشتاییهایی است که در کدگذاری درخواست شده توسط %2 مجاز نیستند.</translation> + </message> + <message> + <source>The codepoint %1, occurring in %2 using encoding %3, is an invalid XML character.</source> + <translation>کدنقطهٔ %1، در %2 واقع میشود از کدگذاری %3 استفاده میکند، یک نویسهٔ XML نامعتبر است.</translation> + </message> + <message> + <source>Network timeout.</source> + <translation>وقفهٔ زمانی شبکه.</translation> + </message> + <message> + <source>Element %1 can't be serialized because it appears outside the document element.</source> + <translation>عنصر %1 نمیتواند سریالیزه شود زیرا خارج از عنصر سند به نظر میرسد.</translation> + </message> + <message> + <source>Attribute %1 can't be serialized because it appears at the top level.</source> + <translation>صفت %1 نمیتواند مرتب شود زیرا در سطح بالا به نظر میرسد.</translation> + </message> + <message> + <source>Year %1 is invalid because it begins with %2.</source> + <translation>سال %1 نامعتبر است زیرا با %2 شروع میشود.</translation> + </message> + <message> + <source>Day %1 is outside the range %2..%3.</source> + <translation>روز %1 خارج از دامنهٔ %2 است..%3.</translation> + </message> + <message> + <source>Month %1 is outside the range %2..%3.</source> + <translation>ماه %1 خارج از دامنهٔ %2 است..%3.</translation> + </message> + <message> + <source>Overflow: Can't represent date %1.</source> + <translation>سرریز: نمیتوان تاریخ %1 را نمایش داد.</translation> + </message> + <message> + <source>Day %1 is invalid for month %2.</source> + <translation>روز %1 برای ماه %2 نامعتبر است.</translation> + </message> + <message> + <source>Time 24:%1:%2.%3 is invalid. Hour is 24, but minutes, seconds, and milliseconds are not all 0; </source> + <translation>زمان ۲۴ ساعتی: %1 %2 %3 نامعتبر است. زمان ۲۴ ساعتی است اما دقیقه، ثانیه و میلیثانیه صفر نیستند؛</translation> + </message> + <message> + <source>Time %1:%2:%3.%4 is invalid.</source> + <translation>زمان %1:%2:%3.%4 نامعتبر است.</translation> + </message> + <message> + <source>Overflow: Date can't be represented.</source> + <translation>سرریز: نمیتوان تاریخ را نمایش داد.</translation> + </message> + <message> + <source>At least one component must be present.</source> + <translation>حداقل یک جزء باید نمایش داده شود.</translation> + </message> + <message> + <source>At least one time component must appear after the %1-delimiter.</source> + <translation>حداقل یک جزء زمان باید بعد از حائل %1 ظاهر شود.</translation> + </message> + <message> + <source>%1 is not a valid value of type %2.</source> + <translation>%1 یک مقدار معتبر از نوع %2 نیست.</translation> + </message> + <message> + <source>When casting to %1 from %2, the source value cannot be %3.</source> + <translation>هنگام تبدیل از %2 به %1، مقدار مبدأ نمیتواند %3 شود.</translation> + </message> + <message> + <source>Integer division (%1) by zero (%2) is undefined.</source> + <translation>تقسیم صحیح (%1) بر صفر (%2) تعریف نشده است.</translation> + </message> + <message> + <source>Division (%1) by zero (%2) is undefined.</source> + <translation>تقسیم (%1) بر صفر (%2) تعریف نشده است.</translation> + </message> + <message> + <source>Modulus division (%1) by zero (%2) is undefined.</source> + <translation>باقیماندهگیری (%1) از صفر (%2) تعریف نشده است.</translation> + </message> + <message> + <source>Dividing a value of type %1 by %2 (not-a-number) is not allowed.</source> + <translation>تقسیم مقادیر از نوع %1 بر %2 (غیر عددی) مجاز نیست.</translation> + </message> + <message> + <source>Dividing a value of type %1 by %2 or %3 (plus or minus zero) is not allowed.</source> + <translation>تقسیم مقادیر از نوع %1 بر %2 یا %3 (+ یا - صفر) مجاز نیست.</translation> + </message> + <message> + <source>Multiplication of a value of type %1 by %2 or %3 (plus or minus infinity) is not allowed.</source> + <translation>ضرب مقادیر از نوع %1 در %2 یا %3 (+ یا - بینهایت) مجاز نیست.</translation> + </message> + <message> + <source>A value of type %1 cannot have an Effective Boolean Value.</source> + <translation>مقدار از نوع %1 نمیتواند مقدار مؤثر منطقی داشتهباشد.</translation> + </message> + <message> + <source>Effective Boolean Value cannot be calculated for a sequence containing two or more atomic values.</source> + <translation>مقدار مؤثر بولین نمیتواند برای رشتهای با دو یا چند مقدار اتمی محاسبه شود.</translation> + </message> + <message> + <source>Value %1 of type %2 exceeds maximum (%3).</source> + <translation>مقدار %1 از نوع %2 از حد ماکزیمم (%3) تجاوز میکند.</translation> + </message> + <message> + <source>Value %1 of type %2 is below minimum (%3).</source> + <translation>مقدار %1 از نوع %2 زیر حد کمینه (%3) است.</translation> + </message> + <message> + <source>A value of type %1 must contain an even number of digits. The value %2 does not.</source> + <translation>یک مقدار از نوع %1 باید تعداد زوج اعداد باشد. مقدار %2 این طور نیست.</translation> + </message> + <message> + <source>%1 is not valid as a value of type %2.</source> + <translation>%1 به عنوان مقداری از نوع %2 معتبر نیست.</translation> + </message> + <message> + <source>Ambiguous rule match.</source> + <translation>قاعدهٔ تطبیق مبهم.</translation> + </message> + <message> + <source>Operator %1 cannot be used on type %2.</source> + <translation>عملگر %1 روی نوع %2 قابل اجرا نیست.</translation> + </message> + <message> + <source>Operator %1 cannot be used on atomic values of type %2 and %3.</source> + <translation>عملگر %1 روی مقادیر اتمی از نوع %2 و %3 قابل اجرا نیست.</translation> + </message> + <message> + <source>The namespace URI in the name for a computed attribute cannot be %1.</source> + <translation>نام فضاینامی URL برای یک صفت محاسبه شده نمیتواند %1 باشد.</translation> + </message> + <message> + <source>The name for a computed attribute cannot have the namespace URI %1 with the local name %2.</source> + <translation>نام صفت محاسبه شده نمیتواند فضای نامی URL %1 را با نام محلی %2 داشته باشد.</translation> + </message> + <message> + <source>Type error in cast, expected %1, received %2.</source> + <translation>خطای نوع در تبدیل، مورد انتظار %1، دریافت شده %2.</translation> + </message> + <message> + <source>When casting to %1 or types derived from it, the source value must be of the same type, or it must be a string literal. Type %2 is not allowed.</source> + <translation>هنگامی که به %1 تبدیل میکنیم با انواع از آن مشتق میشوند، مقدار اولیه باید همان یا رشته باشد. نوع %2 مجاز نیست.</translation> + </message> + <message> + <source>A comment cannot contain %1</source> + <translation>یک توضیح نمیتواند شامل %1 باشد</translation> + </message> + <message> + <source>A comment cannot end with a %1.</source> + <translation>یک توضیح نمیتواند با یک %1 تمام شود.</translation> + </message> + <message> + <source>In a namespace constructor, the value for a namespace cannot be an empty string.</source> + <translation>در یک سازندهٔ فضاینامی، مقدار فضاینامی نمیتواند یک رشتهٔ خالی باشد.</translation> + </message> + <message> + <source>The prefix must be a valid %1, which %2 is not.</source> + <translation>پیشوند باید یک %1 معتبر باشد، که %2 نیست.</translation> + </message> + <message> + <source>The prefix %1 cannot be bound.</source> + <translation>پیشوند %1 نمیتواند مقید شود.</translation> + </message> + <message> + <source>Only the prefix %1 can be bound to %2 and vice versa.</source> + <translation>فقط پیشوند %1 میتواند به %2 مقید شود و برعکس.</translation> + </message> + <message> + <source>An attribute node cannot be a child of a document node. Therefore, the attribute %1 is out of place.</source> + <translation>یک گرهٔ صفت نمیتواند فرزند یک گرهٔ سند باشد. بنابراین، صفت %1 خارج از مکان است.</translation> + </message> + <message> + <source>A library module cannot be evaluated directly. It must be imported from a main module.</source> + <translation>یک ماژول کتابخانهای نمیتواند به تنهایی بررسی شود. آن باید از یک ماژول اصلی وارد شود.</translation> + </message> + <message> + <source>No template by name %1 exists.</source> + <translation>هیچ قالبی با نام %1 وجود ندارد.</translation> + </message> + <message> + <source>A value of type %1 cannot be a predicate. A predicate must have either a numeric type or an Effective Boolean Value type.</source> + <translation>یک نوع نامعتبر %1 نمیتواند مستند باشد. یک مستند باید یک نوع عددی یا یک نوع مؤثر بولین داشته باشد.</translation> + </message> + <message> + <source>A positional predicate must evaluate to a single numeric value.</source> + <translation>یک مستند وابسته به موقعیت باید نسبت به یک مقدار عددی تک ارزیابی شود.</translation> + </message> + <message> + <source>The target name in a processing instruction cannot be %1 in any combination of upper and lower case. Therefore, %2 is invalid.</source> + <translation>نام هدف در دستورالعمل پردازش نمیتواند در هر ترکیب از حروف بزرگ و کوچک %1 باشد. بنابراین، %2 نامعتبر است.</translation> + </message> + <message> + <source>%1 is not a valid target name in a processing instruction. It must be a %2 value, e.g. %3.</source> + <translation>%1 یک نام هدف معتبر در دستورالعمل پردازش نیست. آن باید یک مقدار %2 باشد، برای مثال %3.</translation> + </message> + <message> + <source>The last step in a path must contain either nodes or atomic values. It cannot be a mixture between the two.</source> + <translation>آخرین گام در یک مسیر باید شامل گره یا مقدار اتمی باشد. آن نمیتواند ترکیبی بین هردو باشد.</translation> + </message> + <message> + <source>The data of a processing instruction cannot contain the string %1</source> + <translation>دادهٔ دستورالعمل پردازش نمیتواند شامل رشتهٔ %1 باشد</translation> + </message> + <message> + <source>No namespace binding exists for the prefix %1</source> + <translation>هیچ مقیدسازی فضاینامی برای پیشوند %1 وجود ندارد</translation> + </message> + <message> + <source>No namespace binding exists for the prefix %1 in %2</source> + <translation>هیچ مقیدسازی فضاینامی برای پیشوند %1 در %2 وجود ندارد</translation> + </message> + <message> + <source>%1 is an invalid %2</source> + <translation>%1 یک %2 نامعتبر است</translation> + </message> + <message> + <source>The parameter %1 is passed, but no corresponding %2 exists.</source> + <translation>پارامتر %1 پاس شده است، اما مترادف %2 وجود ندارد.</translation> + </message> + <message> + <source>The parameter %1 is required, but no corresponding %2 is supplied.</source> + <translation>پارامتر %1 مورد نیاز است است، اما مترادف %2 تأمین نشده است.</translation> + </message> + <message numerus="yes"> + <source>%1 takes at most %n argument(s). %2 is therefore invalid.</source> + <translation> + <numerusform>%1 حداکثر %n آرگومان میگیرد. بنابراین %2 نامعتبر است.</numerusform> + </translation> + </message> + <message numerus="yes"> + <source>%1 requires at least %n argument(s). %2 is therefore invalid.</source> + <translation> + <numerusform>%1 لااقل %n آرگومان نیاز دارد. بنابراین %2 نامعتبر است.</numerusform> + </translation> + </message> + <message> + <source>The first argument to %1 cannot be of type %2. It must be a numeric type, xs:yearMonthDuration or xs:dayTimeDuration.</source> + <translation>اولین آرگومان به %1 نمیتواند از نوع %2 باشد. آن باید یک نوع عددی، xs:yearMonthDuratin یا xs::dayTimeDuration باشد.</translation> + </message> + <message> + <source>The first argument to %1 cannot be of type %2. It must be of type %3, %4, or %5.</source> + <translation>اولین آرگومان به %1 نمیتواند از نوع %2 باشد. آن باید از نوع %3، %4 یا %5 باشد.</translation> + </message> + <message> + <source>The second argument to %1 cannot be of type %2. It must be of type %3, %4, or %5.</source> + <translation>دومین آرگومان به %1 نمیتواند از نوع %2 باشد. آن باید از نوع %3، %4 یا %5 باشد.</translation> + </message> + <message> + <source>%1 is not a valid XML 1.0 character.</source> + <translation>%1 یک کاراکتر معتبر 1.0 XML نیست.</translation> + </message> + <message> + <source>The root node of the second argument to function %1 must be a document node. %2 is not a document node.</source> + <translation>گره ریشهٔ دومین آرگومان به تابع %1 باید یک گره سند باشد. %2 یک گره سند نیست.</translation> + </message> + <message> + <source>If both values have zone offsets, they must have the same zone offset. %1 and %2 are not the same.</source> + <translation>اگر هر دو مقدار انحراف ناحیهای دارند انحراف ناحیهای آنها باید برابر باشد. %1 و %2 یکی نیستند.</translation> + </message> + <message> + <source>%1 was called.</source> + <translation>%1 فراخوانی شده بود.</translation> + </message> + <message> + <source>%1 must be followed by %2 or %3, not at the end of the replacement string.</source> + <translation>%1 باید با %2 یا %3 همراه شود، نه در پایان رشتهٔ جایگزین.</translation> + </message> + <message> + <source>In the replacement string, %1 must be followed by at least one digit when not escaped.</source> + <translation>در رشتهٔ جایگزین، %1 هنگامی که شناسهٔ فرار نیست باید حداقل با یک رقم همراه شود.</translation> + </message> + <message> + <source>In the replacement string, %1 can only be used to escape itself or %2, not %3</source> + <translation>در رشتهٔ جایگزین، %1 فقط باید برای فرار از %2 یا خودش استفاده شود، نه %3</translation> + </message> + <message> + <source>%1 matches newline characters</source> + <translation>%1 با کاراکتر خطجدید مطابقت دارد</translation> + </message> + <message> + <source>%1 and %2 match the start and end of a line.</source> + <translation>%1 و %2 شروع و پایان یک خط را جور میکنند.</translation> + </message> + <message> + <source>Matches are case insensitive</source> + <translation>تطابقها حساس به حالت هستند</translation> + </message> + <message> + <source>Whitespace characters are removed, except when they appear in character classes</source> + <translation>کاراکترهای فضای خالی حذف میشوند به جز مواردی که در ردههای کاراکتر پیدا شوند</translation> + </message> + <message> + <source>%1 is an invalid regular expression pattern: %2</source> + <translation>%1 یک الگوی عبارت منظم نامعتبر است: %2</translation> + </message> + <message> + <source>%1 is an invalid flag for regular expressions. Valid flags are:</source> + <translation>%1 یک پرچم نامعتبر برای عبارات منظم است. پرچمهای معتبر اینها هستند:</translation> + </message> + <message> + <source>If the first argument is the empty sequence or a zero-length string (no namespace), a prefix cannot be specified. Prefix %1 was specified.</source> + <translation>اگر اولین آرگومان خالی یا یک رشته با طول صفر باشد، یک پیشوند نمیتواند مشخص شود. پیشوند %1 مشخص شده بود.</translation> + </message> + <message> + <source>It will not be possible to retrieve %1.</source> + <translation>امکان بازیابی %1 وجود ندارد.</translation> + </message> + <message> + <source>The default collection is undefined</source> + <translation>مجموعهٔ پیشفرض تعریف نشده است</translation> + </message> + <message> + <source>%1 cannot be retrieved</source> + <translation>نمیتوان %1 را بازیابی کرد</translation> + </message> + <message> + <source>The normalization form %1 is unsupported. The supported forms are %2, %3, %4, and %5, and none, i.e. the empty string (no normalization).</source> + <translation>نرمالسازی از %1 پشتیبانی نشده است. شکلهای پشتیبانی شده %2، %3، %4، %5 و رشته خالی هستند.</translation> + </message> + <message> + <source>A zone offset must be in the range %1..%2 inclusive. %3 is out of range.</source> + <translation>یک انحراف ناحیهای باید شامل محدودهٔ %1 تا %2 باشد. %3 خارج از محدوده است.</translation> + </message> + <message> + <source>%1 is not a whole number of minutes.</source> + <translation>%1 تمام عدد دقیقهها نیست.</translation> + </message> + <message> + <source>The URI cannot have a fragment</source> + <translation>URL نمیتواند شکستگی داشته باشد</translation> + </message> + <message> + <source>Required cardinality is %1; got cardinality %2.</source> + <translation>اصلیت %1 درخواست شد؛ %2 حاصل شد.</translation> + </message> + <message> + <source>The item %1 did not match the required type %2.</source> + <translation>آیتم %1 با نوع موردنیاز %2 مطابقت ندارد.</translation> + </message> + <message> + <source>The variable %1 is unused</source> + <translation>متغیر %1 استفاده نشده است</translation> + </message> + <message> + <source>W3C XML Schema identity constraint selector</source> + <translation>موجودیت طرح XML W3C انتخابکننده را محدود میکند</translation> + </message> + <message> + <source>W3C XML Schema identity constraint field</source> + <translation>موجودیت طرح XML W3C رشته را محدود میکند</translation> + </message> + <message> + <source>A construct was encountered which is disallowed in the current language(%1).</source> + <translation>برخورد با ساختار غیرمجاز در زبان جاری (%1)..</translation> + </message> + <message> + <source>%1 is an unknown schema type.</source> + <translation>%1 نوع ناشناختهٔ طرح نوع.</translation> + </message> + <message> + <source>A template with name %1 has already been declared.</source> + <translation>یک قالب با نام %1 هماکنون بیان شده است.</translation> + </message> + <message> + <source>%1 is not a valid numeric literal.</source> + <translation>%1 یک لفظ عددی نامعتبر است.</translation> + </message> + <message> + <source>Only one %1 declaration can occur in the query prolog.</source> + <translation>فقط اعلان یک %1میتواند در prolog پرسوجویی اتفاق بیفتد.</translation> + </message> + <message> + <source>The initialization of variable %1 depends on itself</source> + <translation>فرمت متغیر %1 به خودش وابسته است</translation> + </message> + <message> + <source>No variable with name %1 exists</source> + <translation>هیچ متغییری با نام %1 وجود ندارد</translation> + </message> + <message> + <source>Version %1 is not supported. The supported XQuery version is 1.0.</source> + <translation>نسخهٔ %1 پشتیبانی نشده است. نسخهٔ پشتیبانی شدهٔ XQuery 1.0است.</translation> + </message> + <message> + <source>The encoding %1 is invalid. It must contain Latin characters only, must not contain whitespace, and must match the regular expression %2.</source> + <translation>کدگذاری %1 نامعتبر است. آن فقط باید شامل حروف لاتین باشد و نباید شامل فضای خالی باشد و همچنین باید با عبارت منظم %2 تطابق داشته باشد.</translation> + </message> + <message> + <source>No function with signature %1 is available</source> + <translation>تابعی با امضای %1 در دسترس نیست</translation> + </message> + <message> + <source>A default namespace declaration must occur before function, variable, and option declarations.</source> + <translation>اعلان یک فضاینامی پیشفرض باید قبل از اعلان تابع، متغیر و گزینهها اتفاق بیفتد.</translation> + </message> + <message> + <source>Namespace declarations must occur before function, variable, and option declarations.</source> + <translation>اعلان فضاینامی باید قبل از اعلان تابع، متغیر و گزینهها اتفاق بیفتد.</translation> + </message> + <message> + <source>Module imports must occur before function, variable, and option declarations.</source> + <translation>واردکردن ماژول باید قبل از اعلان تابع، متغیر و گزینهها اتفاق بیفتد.</translation> + </message> + <message> + <source>The keyword %1 cannot occur with any other mode name.</source> + <translation>کلیدواژهٔ %1 نمیتواند با هیچ اسم حالت دیگری اتفاق بیفتد.</translation> + </message> + <message> + <source>The value of attribute %1 must be of type %2, which %3 isn't.</source> + <translation>مقدار صفت %1 باید از نوع %2 باشد، در حالی که %3 نیست.</translation> + </message> + <message> + <source>It is not possible to redeclare prefix %1.</source> + <translation>نمیتوان پیشوند %1 را دوباره اعلان کرد.</translation> + </message> + <message> + <source>The prefix %1 cannot be bound. By default, it is already bound to the namespace %2.</source> + <translation>پیشوند %1 نمیتواند مقید شود. به طور پیشفرض، آن به فضاینامی %2 مقید شده است.</translation> + </message> + <message> + <source>Prefix %1 is already declared in the prolog.</source> + <translation>پیشوند %1 هماکنون در prolog اعلان شده است.</translation> + </message> + <message> + <source>The name of an option must have a prefix. There is no default namespace for options.</source> + <translation>نام گزینه باید پیشوند داشته باشد. فضاینامی پیشفرضی برای گزینهها وجود ندارد.</translation> + </message> + <message> + <source>The Schema Import feature is not supported, and therefore %1 declarations cannot occur.</source> + <translation>ویژگی واردکردن طرح پشتیبانی نشده است، بنابراین اعلان %1 نمیتواند اتفاق بیفتد.</translation> + </message> + <message> + <source>The target namespace of a %1 cannot be empty.</source> + <translation>فضاینامی هدف %1 نمیتواند خالی باشد.</translation> + </message> + <message> + <source>The module import feature is not supported</source> + <translation>ویژگی واردکردن ماژول پشتیبانی نشده است</translation> + </message> + <message> + <source>A variable with name %1 has already been declared.</source> + <translation>یک متغیر با نام %1 هماکنون اعلان شده است.</translation> + </message> + <message> + <source>No value is available for the external variable with name %1.</source> + <translation>مقداری برای متغیر خارجی با نام %1 در دسترس نیست.</translation> + </message> + <message> + <source>A stylesheet function must have a prefixed name.</source> + <translation>یک تابع مجموعهتعاریف باید یک نام پیشوندی داشته باشد.</translation> + </message> + <message> + <source>The namespace for a user defined function cannot be empty (try the predefined prefix %1 which exists for cases like this)</source> + <translation>فضاینامی برای توابع تعریف شده توسط کاربر نمیتواند خالی باشد(پیشوند از پیش تعریف شدهٔ %1 را که برای این موارد وجود دارد امتحان کنید)</translation> + </message> + <message> + <source>The namespace %1 is reserved; therefore user defined functions may not use it. Try the predefined prefix %2, which exists for these cases.</source> + <translation>فضاینامی %1 رزرو شده است؛ بنابراین توابع تعریف شده توسط کاربر نمیتوانند از آن استفاده کنند. پیشوند از پیش تعریف شدهٔ %2 را که برای این موارد وجود دارد امتحان کنید.</translation> + </message> + <message> + <source>The namespace of a user defined function in a library module must be equivalent to the module namespace. In other words, it should be %1 instead of %2</source> + <translation>فضاینامی یک تابع تعریف شده توسط کاربر در یک ماژول کتابخانهای باید همارز فضاینامی ماژول باشد. به بیان دیگر، باید %1 بهجای %2 باشد</translation> + </message> + <message> + <source>A function already exists with the signature %1.</source> + <translation>یک تابع با امضای %1 هماکنون وجود دارد.</translation> + </message> + <message> + <source>No external functions are supported. All supported functions can be used directly, without first declaring them as external</source> + <translation>هیچ تابع خارجی پشتیبانی نشده است. تمام توابع پشتیبانی شده میتوانند بدون بیان به صورت خارجی در ابتدا، به طور مستقیم استفاده شوند</translation> + </message> + <message> + <source>An argument with name %1 has already been declared. Every argument name must be unique.</source> + <translation>یک آرگومان با نام %1 هماکنون اعلان شده است. نام هر آرگومان باید یکتا باشد.</translation> + </message> + <message> + <source>When function %1 is used for matching inside a pattern, the argument must be a variable reference or a string literal.</source> + <translation>هنگامی که تابع %1 برای تطابق داخل الگو استفاده میشود، آرگومان باید یک اشارهگر به متغر یا رشته باشد.</translation> + </message> + <message> + <source>In an XSL-T pattern, the first argument to function %1 must be a string literal, when used for matching.</source> + <translation>در یک الگوی XSL-T، آرگومان اول تابع %1 هنگامی که برای تطابق استفاده میشود باید رشته باشد.</translation> + </message> + <message> + <source>In an XSL-T pattern, the first argument to function %1 must be a literal or a variable reference, when used for matching.</source> + <translation>در یک الگوی XSL-T، آرگومان اول تابع %1 هنگامی که برای تطابق استفاده میشود باید لفظ یا اشارهگر به متغیر باشد.</translation> + </message> + <message> + <source>In an XSL-T pattern, function %1 cannot have a third argument.</source> + <translation>در یک الگوی XSL-T، تابع %1 نمیتواند آرگومان سوم داشته باشد.</translation> + </message> + <message> + <source>In an XSL-T pattern, only function %1 and %2, not %3, can be used for matching.</source> + <translation>در یک الگوی XSL-T، فقط توابع %1 و %2 نه %3 میتواند برای تطابق استفاده شوند.</translation> + </message> + <message> + <source>In an XSL-T pattern, axis %1 cannot be used, only axis %2 or %3 can.</source> + <translation>در یک الگوی XSL-T، فقط الگوهای %2 و %3 نه %1 میتوانند استفاده شوند.</translation> + </message> + <message> + <source>%1 is an invalid template mode name.</source> + <translation>%1 یک نام حالت قالب نامعتبر است.</translation> + </message> + <message> + <source>The name of a variable bound in a for-expression must be different from the positional variable. Hence, the two variables named %1 collide.</source> + <translation>نام یک متغیر مقید شده برای عبارت باید متفاوت از نام یک متغیر موقعیتی باشد. بنابراین دو متغیر با نام %1 برخورد دارند.</translation> + </message> + <message> + <source>The Schema Validation Feature is not supported. Hence, %1-expressions may not be used.</source> + <translation>ویژگی اعتبارسنجی طرح پشتیبانی نشده است. بنابراین، عبارات-%1 ممکن است استفاده نشود.</translation> + </message> + <message> + <source>None of the pragma expressions are supported. Therefore, a fallback expression must be present</source> + <translation>هیچ عبارت عملی پشتیبانی نشده اسن. بنابراین، یک عبارت عقبنشینی باید ارائه شود</translation> + </message> + <message> + <source>Each name of a template parameter must be unique; %1 is duplicated.</source> + <translation>هر نام پارامتر قالب باید یگانه باشد؛ %1 چندگانه است.</translation> + </message> + <message> + <source>The %1-axis is unsupported in XQuery</source> + <translation>محور %1 در XQuery پشتیبانی نشده است</translation> + </message> + <message> + <source>No function with name %1 is available.</source> + <translation>هیچ تابعی با نام %1 در دسترس نیست.</translation> + </message> + <message> + <source>The namespace URI cannot be the empty string when binding to a prefix, %1.</source> + <translation>فضاینامی URL هنگامی که به یک پیشوند مقید میشود نمیتواند رشتهٔ خالی باشد، %1.</translation> + </message> + <message> + <source>%1 is an invalid namespace URI.</source> + <translation>%1 یک فضای نامی URL نامعتبر است.</translation> + </message> + <message> + <source>It is not possible to bind to the prefix %1</source> + <translation>مقید کردن به پیشوند %1 ممکن نیست</translation> + </message> + <message> + <source>Namespace %1 can only be bound to %2 (and it is, in either case, pre-declared).</source> + <translation>فضاینامی %1 فقط میتواند به %2 مقید شود (در هر حالتی پیش اعلان شده است).</translation> + </message> + <message> + <source>Prefix %1 can only be bound to %2 (and it is, in either case, pre-declared).</source> + <translation>پیشوند %1 فقط میتواند به %2 مقید شود (در هر حالتی پیش اعلان شده است).</translation> + </message> + <message> + <source>Two namespace declaration attributes have the same name: %1.</source> + <translation>صفتهای اعلان دو فضای نام دارای یک نام هستند: %1.</translation> + </message> + <message> + <source>The namespace URI must be a constant and cannot use enclosed expressions.</source> + <translation>فضاینامی URL باید ثابت باشد و نمیتواند به عبارات بپیوندد.</translation> + </message> + <message> + <source>An attribute with name %1 has already appeared on this element.</source> + <translation>یک صفت با نام %1 هماکنون در این عنصر شده است.</translation> + </message> + <message> + <source>A direct element constructor is not well-formed. %1 is ended with %2.</source> + <translation>سازندهٔ مستقیم یک عنصر خوشفرم نیست. %1 با %2 تمام شده است.</translation> + </message> + <message> + <source>The name %1 does not refer to any schema type.</source> + <translation>نام %1 به هیچ نوع طرحی اشاره نمیکند.</translation> + </message> + <message> + <source>%1 is an complex type. Casting to complex types is not possible. However, casting to atomic types such as %2 works.</source> + <translation>%1 یک نوع پیچیده است. تبدیل به نوع پیچیده غیرممکن است. اما تبدیل به انواع اتمی مثل %2 کار میکند.</translation> + </message> + <message> + <source>%1 is not an atomic type. Casting is only possible to atomic types.</source> + <translation>%1 یک نوع اتمی نیست. تبدیل فقط برای انواع اتمی ممکن است.</translation> + </message> + <message> + <source>%1 is not a valid name for a processing-instruction.</source> + <translation>%1 یک نام معتبر برای دستوراعمل پردازش نیست.</translation> + </message> + <message> + <source>%1 is not in the in-scope attribute declarations. Note that the schema import feature is not supported.</source> + <translation>%1 یک اعلان صفت درون قلمرویی نیست. توجه کنید که ویژگی واردکردن طرح پشتیبانی نشده است.</translation> + </message> + <message> + <source>The name of an extension expression must be in a namespace.</source> + <translation>نام یک عبارت توسعه داده شده باید در فضاینامی باشد.</translation> + </message> + <message> + <source>Element %1 is not allowed at this location.</source> + <translation>عنصر %1 در این مکان مجاز نیست.</translation> + </message> + <message> + <source>Text nodes are not allowed at this location.</source> + <translation>گرههای متن در این مکان مجاز نیستند.</translation> + </message> + <message> + <source>Parse error: %1</source> + <translation>خطای تحلیل: %1</translation> + </message> + <message> + <source>The value of the XSL-T version attribute must be a value of type %1, which %2 isn't.</source> + <translation>مقدار صفت ورژن XSL-T باید از نوع %1 باشد در حالی که %2 نیست.</translation> + </message> + <message> + <source>Running an XSL-T 1.0 stylesheet with a 2.0 processor.</source> + <translation>اجرای یک مجموعهتعاریف 1.0 XSL-T با یک پردازنده 2.0.</translation> + </message> + <message> + <source>Unknown XSL-T attribute %1.</source> + <translation>صفت ناشناخته %1 XSL-T.</translation> + </message> + <message> + <source>Attribute %1 and %2 are mutually exclusive.</source> + <translation>صفات %1 و %2 متقابلاً انحصاری هستند.</translation> + </message> + <message> + <source>In a simplified stylesheet module, attribute %1 must be present.</source> + <translation>در یک ماژول مجموعه تعاریف ساده شده، صفت %1 باید ارائه شود.</translation> + </message> + <message> + <source>If element %1 has no attribute %2, it cannot have attribute %3 or %4.</source> + <translation>اگر عنصر %1 صفت %2 را نداشته باشد، نمیتواند صفت %3 یا %4 را داشته باشد.</translation> + </message> + <message> + <source>Element %1 must have at least one of the attributes %2 or %3.</source> + <translation>عنصر %1 باید حداقل یکی از صفات %2 یا %3 را داشته باشد.</translation> + </message> + <message> + <source>At least one mode must be specified in the %1-attribute on element %2.</source> + <translation>حداقل یک حالت باید به صورت صفت %1 در عنصر %2 مشخص شود.</translation> + </message> + <message> + <source>Element %1 must come last.</source> + <translation>عنصر %1 باید در آخر بیاید.</translation> + </message> + <message> + <source>At least one %1-element must occur before %2.</source> + <translation>حداقل یک عنصر %1 قبل از %2 باید واقع شود.</translation> + </message> + <message> + <source>Only one %1-element can appear.</source> + <translation>فقط یک عنصر %1 میتواند ظاهر شود.</translation> + </message> + <message> + <source>At least one %1-element must occur inside %2.</source> + <translation>حداقل یک عنصر %1 باید داخل %2 واقع شود.</translation> + </message> + <message> + <source>When attribute %1 is present on %2, a sequence constructor cannot be used.</source> + <translation>هنگامی که صفت %1 روی %2 ارائه میشود، یک سازندهٔ رشته نمیتواند استفاده شود.</translation> + </message> + <message> + <source>Element %1 must have either a %2-attribute or a sequence constructor.</source> + <translation>عنصر %1 باید یک صفت %2 یا یک سازندهٔ رشته داشته باشد.</translation> + </message> + <message> + <source>When a parameter is required, a default value cannot be supplied through a %1-attribute or a sequence constructor.</source> + <translation>هنگامی که یک پارامتر موردنیاز است، یک مقدار پیشفرض نمیتواند به واسطهٔ صفت %1 یا سازندهٔ رشته تأمین شود.</translation> + </message> + <message> + <source>Element %1 cannot have children.</source> + <translation>عنصر %1 نمیتواند فرزند داشته باشد.</translation> + </message> + <message> + <source>Element %1 cannot have a sequence constructor.</source> + <translation>عنصر %1 نمیتواند سازندهٔ رشته داشته باشد.</translation> + </message> + <message> + <source>The attribute %1 cannot appear on %2, when it is a child of %3.</source> + <translation>صفت %1 نمیتواند روی %2 ظاهر شود، در حالی که فرزند %3 است.</translation> + </message> + <message> + <source>A parameter in a function cannot be declared to be a tunnel.</source> + <translation>یک پارامتر در یک تابع نمیتواند به عنوان تونل اعلان شود.</translation> + </message> + <message> + <source>This processor is not Schema-aware and therefore %1 cannot be used.</source> + <translation>این پردازنده طرح-آگاه نیست بنابراین %1 نمیتواند استفاده شود.</translation> + </message> + <message> + <source>Top level stylesheet elements must be in a non-null namespace, which %1 isn't.</source> + <translation>عنصر مجموعهٔ تعریف سطح بالا باید یک فضاینامی غیرتهی باشد، در حالی که %1 نیست.</translation> + </message> + <message> + <source>The value for attribute %1 on element %2 must either be %3 or %4, not %5.</source> + <translation>مقدار صفت %1 روی عنصر %2 باید %3 یا %4 باشد، نه %5.</translation> + </message> + <message> + <source>Attribute %1 cannot have the value %2.</source> + <translation>صفت %1 نمیتواند مقدار %2 داشته باشد.</translation> + </message> + <message> + <source>The attribute %1 can only appear on the first %2 element.</source> + <translation>صفت %1 فقط میتواند روی %2 عنصر اول به نظر برسد.</translation> + </message> + <message> + <source>At least one %1 element must appear as child of %2.</source> + <translation>حداقل یک عنصر %1 باید به عنوان فرزند %2 ظاهر شود.</translation> + </message> + <message> + <source>Empty particle cannot be derived from non-empty particle.</source> + <translation>یک ذرهٔ تهی نمیتواند از یک ذرهٔ غیرتهی مشتق شود.</translation> + </message> + <message> + <source>Derived particle is missing element %1.</source> + <translation>ذرهٔ مشتق شده عنصر گمشدهٔ %1 است.</translation> + </message> + <message> + <source>Derived element %1 is missing value constraint as defined in base particle.</source> + <translation>عنصر مشتق شدهٔ %1 مقدار گمشدهایست که در ذرهٔ پایهٔ به عنوان تعریف شده مقید شده.</translation> + </message> + <message> + <source>Derived element %1 has weaker value constraint than base particle.</source> + <translation>عنصر مشتق شده %1 مقدار ضعیفتری دارد که از عنصر پایه مقید میشود.</translation> + </message> + <message> + <source>Fixed value constraint of element %1 differs from value constraint in base particle.</source> + <translation>مقدار اصلاح شدهای که از عنصر %1 مقید میشود از مقداری که از عنصر پایه مقید میشود متفاوت است.</translation> + </message> + <message> + <source>Derived element %1 cannot be nillable as base element is not nillable.</source> + <translation>عنصر مشتق شده %1 همان طور که عنصر پایهاش nillable نیست نمیتواند nillable باشد.</translation> + </message> + <message> + <source>Block constraints of derived element %1 must not be more weaker than in the base element.</source> + <translation>بلاکی که از عنصر مشتق شده %1 مقید میشود نباید از عنصر پایه ضعیفتر باشد.</translation> + </message> + <message> + <source>Simple type of derived element %1 cannot be validly derived from base element.</source> + <translation>نوع سادهٔ مشتق شده از عنصر %1 نمیتواند به طور معتبر از عنصر پایه مشتق شود.</translation> + </message> + <message> + <source>Complex type of derived element %1 cannot be validly derived from base element.</source> + <translation>نوع پیچیدهٔ مشتق شده از عنصر %1 نمیتواند به طور معتبر از عنصر پایه مشتق شود.</translation> + </message> + <message> + <source>Element %1 is missing in derived particle.</source> + <translation>عنصر %1 در جزء مشتقشده گم شده است.</translation> + </message> + <message> + <source>Element %1 does not match namespace constraint of wildcard in base particle.</source> + <translation>عنصر %1 با فضاینامی که از حرف جایگزین شونده در عنصر پایه مقید میشود تطابق ندارد.</translation> + </message> + <message> + <source>Wildcard in derived particle is not a valid subset of wildcard in base particle.</source> + <translation>حرف جایگزین شونده در عنصر مشتق شده یک زیرمجموعه معتبر از حرف جایگزین شونده در عنصر پایه نیست.</translation> + </message> + <message> + <source>processContent of wildcard in derived particle is weaker than wildcard in base particle.</source> + <translation>محتویات پردازش حرف جایگزین شونده در عنصر مشتق شده از حرف جایگزین شونده در عنصر پایه ضعیفتر است.</translation> + </message> + <message> + <source>Derived particle allows content that is not allowed in the base particle.</source> + <translation>محتویات غیرمجاز در عنصر پایه در عنصر مشتق شده مجازند.</translation> + </message> + <message> + <source>%1 has inheritance loop in its base type %2.</source> + <translation>%1 در نوع %2 پایهاش حلقهٔ وراثت دارد.</translation> + </message> + <message> + <source>Circular inheritance of base type %1.</source> + <translation>وراثت گردشی پایهٔ نوع %1.</translation> + </message> + <message> + <source>Circular inheritance of union %1.</source> + <translation>وراثت گردشی اتحاد %1.</translation> + </message> + <message> + <source>%1 is not allowed to derive from %2 by restriction as the latter defines it as final.</source> + <translation>%1 نمیتواند با شرط از %2 مشتق شود مانند نویسهای که آن را به عنوان نهایی تعریف میکند.</translation> + </message> + <message> + <source>%1 is not allowed to derive from %2 by extension as the latter defines it as final.</source> + <translation>%1 نمیتواند با پسوند از %2 مشتق شود مانند نویسهای که آن را به عنوان نهایی تعریف میکند.</translation> + </message> + <message> + <source>Base type of simple type %1 cannot be complex type %2.</source> + <translation>نوع پایهٔ نوع سادهٔ %1 نمیتواند نوع پیچیدهٔ %2 باشد.</translation> + </message> + <message> + <source>Simple type %1 cannot have direct base type %2.</source> + <translation>نوع سادهٔ %1 نمیتواند نوع پایهٔ مستقیم %2 را باشد.</translation> + </message> + <message> + <source>Simple type %1 is not allowed to have base type %2.</source> + <translation>نوع سادهٔ %1 مجاز نیست نوع پایهٔ مستقیم %2 را داشته باشد.</translation> + </message> + <message> + <source>Simple type %1 can only have simple atomic type as base type.</source> + <translation>نوع سادهٔ %1 فقط میتواند نوع سادهٔ اتمی را به عنوان نوع پایه داشته باشد.</translation> + </message> + <message> + <source>Simple type %1 cannot derive from %2 as the latter defines restriction as final.</source> + <translation>%1 نمیتواند از %2 مشتق شود مانند نویسهای که قید را به عنوان نهایی تعریف میکند.</translation> + </message> + <message> + <source>Variety of item type of %1 must be either atomic or union.</source> + <translation>نوع آیتم نوع %1 باید اتمی یا اتحاد باشد.</translation> + </message> + <message> + <source>Variety of member types of %1 must be atomic.</source> + <translation>نوع عضو نوع %1 باید اتمی باشد.</translation> + </message> + <message> + <source>%1 is not allowed to derive from %2 by list as the latter defines it as final.</source> + <translation>%1 نمیتواند با لیست از %2 مشتق شود مانند نویسهای که آن را به عنوان نهایی تعریف میکند.</translation> + </message> + <message> + <source>Simple type %1 is only allowed to have %2 facet.</source> + <translation>نوع سادهٔ %1 فقط مجاز است رویهٔ %2 را داشته باشد.</translation> + </message> + <message> + <source>Base type of simple type %1 must have variety of type list.</source> + <translation>نوع پایهٔ نوع سادهٔ %1 باید از نوع لیست باشد.</translation> + </message> + <message> + <source>Base type of simple type %1 has defined derivation by restriction as final.</source> + <translation>نوع پایهٔ نوع سادهٔ %1 اشتقاق را با قید پایانی تعریف کرده است.</translation> + </message> + <message> + <source>Item type of base type does not match item type of %1.</source> + <translation>آیتم نوع پایه با آیتم نوع %1 مطابقت ندارد.</translation> + </message> + <message> + <source>Simple type %1 contains not allowed facet type %2.</source> + <translation>نوع سادهٔ %1 شامل رویهٔ غیرمجاز نوع %2 است.</translation> + </message> + <message> + <source>%1 is not allowed to derive from %2 by union as the latter defines it as final.</source> + <translation>%1 نمیتواند با اتحاد از %2 مشتق شود مانند نویسهای که آن را به عنوان نهایی تعریف میکند.</translation> + </message> + <message> + <source>%1 is not allowed to have any facets.</source> + <translation>نوع سادهٔ %1 مجاز نیست هیچ رویهای داشته باشد.</translation> + </message> + <message> + <source>Base type %1 of simple type %2 must have variety of union.</source> + <translation>نوع پایهٔ %1 نوع سادهٔ %2 بایدازنوع اتحاد باشد.</translation> + </message> + <message> + <source>Base type %1 of simple type %2 is not allowed to have restriction in %3 attribute.</source> + <translation>نوع پایهٔ %1 نوع سادهٔ %2 مجاز نیست در صفت %3 محدودیت داشته باشد.</translation> + </message> + <message> + <source>Member type %1 cannot be derived from member type %2 of %3's base type %4.</source> + <translation>نوع %1 نمیتواند از نوع %2 نوع %4 پایهٔ %3 مشتق شود.</translation> + </message> + <message> + <source>Derivation method of %1 must be extension because the base type %2 is a simple type.</source> + <translation>روش اشتقاق %1 باید پسوند باشد زیرا پایهٔ نوع %2 ساده است.</translation> + </message> + <message> + <source>Complex type %1 has duplicated element %2 in its content model.</source> + <translation>نوع پیچیدهٔ %1 در مدل محتویاتش عنصر چندگانهٔ %2 را دارد.</translation> + </message> + <message> + <source>Complex type %1 has non-deterministic content.</source> + <translation>نوع پیچیدهٔ %1 محتویات غیرقطعی دارد.</translation> + </message> + <message> + <source>Attributes of complex type %1 are not a valid extension of the attributes of base type %2: %3.</source> + <translation>صفات نوع پیچیدهٔ %1 پسوند معتبر صفات نوع پایهٔ %2 نیستند: %3.</translation> + </message> + <message> + <source>Content model of complex type %1 is not a valid extension of content model of %2.</source> + <translation>مدل محتویات نوع پیچیدهٔ %1 پسوند معتبر مدل محتویات %2 نیستند.</translation> + </message> + <message> + <source>Complex type %1 must have simple content.</source> + <translation>نوع پیچیدهٔ %1 باید محتویات ساده داشته باشد.</translation> + </message> + <message> + <source>Complex type %1 must have the same simple type as its base class %2.</source> + <translation>نوع پیچیدهٔ %1 باید همان انواع ساده را مانند کلاس %2 پایهاش داشته باشد.</translation> + </message> + <message> + <source>Complex type %1 cannot be derived from base type %2%3.</source> + <translation>نوع پیچیدهٔ %1 نمیتواند از نوع %2%3 مشتق شود.</translation> + </message> + <message> + <source>Attributes of complex type %1 are not a valid restriction from the attributes of base type %2: %3.</source> + <translation>صفات نوع پیچیدهٔ %1 قید معتبری از صفات نوع پایهٔ %2 نیستند: %3.</translation> + </message> + <message> + <source>Complex type %1 with simple content cannot be derived from complex base type %2.</source> + <translation>نوع پیچیدهٔ %1 با محتویات ساده نمیتواند از نوع پیچیدهٔ %2 مشتق شود.</translation> + </message> + <message> + <source>Item type of simple type %1 cannot be a complex type.</source> + <translation>نوع آیتم نوع سادهٔ %1 نمیتواند نوع پیچیده باشد.</translation> + </message> + <message> + <source>Member type of simple type %1 cannot be a complex type.</source> + <translation>اعضای نوع سادهٔ %1 نمیتوانند پیچیده باشند.</translation> + </message> + <message> + <source>%1 is not allowed to have a member type with the same name as itself.</source> + <translation>%1 نمیتواند عضوی همنام خودش داشته باشد.</translation> + </message> + <message> + <source>%1 facet collides with %2 facet.</source> + <translation>رویهٔ %1 با %2 تداخل دارد.</translation> + </message> + <message> + <source>%1 facet must have the same value as %2 facet of base type.</source> + <translation>رویهٔ %1 باید همان مقدار رویهٔ %2 نوع پایه باشد.</translation> + </message> + <message> + <source>%1 facet must be equal or greater than %2 facet of base type.</source> + <translation>رویهٔ %1 باید بزرگتر یا مساوی رویهٔ %2 نوع پایه باشد.</translation> + </message> + <message> + <source>%1 facet must be less than or equal to %2 facet of base type.</source> + <translation>رویهٔ %1 باید کوچکتر یا مساوی رویهٔ %2 نوع پایه باشد.</translation> + </message> + <message> + <source>%1 facet contains invalid regular expression</source> + <translation>رویهٔ %1 شامل عبارت منظم نامعتبر است</translation> + </message> + <message> + <source>Unknown notation %1 used in %2 facet.</source> + <translation>نشانهگذاری ناشناختهٔ %1 در رویهٔ %2 استفاده شده است.</translation> + </message> + <message> + <source>%1 facet contains invalid value %2: %3.</source> + <translation>رویه %1 شامل مقدار نامعتبر %2 است: %3.</translation> + </message> + <message> + <source>%1 facet cannot be %2 or %3 if %4 facet of base type is %5.</source> + <translation>رویهٔ %1 نمیتواند %2 یا %3 باشد اگر رویهٔ %4 نوع پایه %5 باشد.</translation> + </message> + <message> + <source>%1 facet cannot be %2 if %3 facet of base type is %4.</source> + <translation>رویهٔ %1 نمیتواند %2 باشد اگر رویهٔ %3 نوع پایه %4 باشد.</translation> + </message> + <message> + <source>%1 facet must be less than or equal to %2 facet.</source> + <translation>رویهٔ %1 باید کوچکتر یا مساوی رویهٔ %2 باشد.</translation> + </message> + <message> + <source>%1 facet must be less than %2 facet of base type.</source> + <translation>رویهٔ %1 باید کوچکتر از رویهٔ %2 نوع پایه باشد.</translation> + </message> + <message> + <source>%1 facet and %2 facet cannot appear together.</source> + <translation>رویههای %1 و %2 نمیتوانند با هم ظاهر شوند.</translation> + </message> + <message> + <source>%1 facet must be greater than %2 facet of base type.</source> + <translation>رویهٔ %1 باید بزرگتر از رویهٔ %2 نوع پایه باشد.</translation> + </message> + <message> + <source>%1 facet must be less than %2 facet.</source> + <translation>رویهٔ %1 باید کوچکتر از رویهٔ %2 باشد.</translation> + </message> + <message> + <source>%1 facet must be greater than or equal to %2 facet of base type.</source> + <translation>رویهٔ %1 باید بزرگتر یا مساوی رویهٔ %2 نوع پایه باشد.</translation> + </message> + <message> + <source>Simple type contains not allowed facet %1.</source> + <translation>نوع ساده شامل رویهٔ غیر مجاز %1 است.</translation> + </message> + <message> + <source>%1, %2, %3, %4, %5 and %6 facets are not allowed when derived by list.</source> + <translation>رویههای %1، %2، %3، %4، %5 و %6 هنگامی که بهوسیلهٔ لیست مشتق میشوند مجاز نیستند.</translation> + </message> + <message> + <source>Only %1 and %2 facets are allowed when derived by union.</source> + <translation>فقط رویههای %1 و %2 هنگامی که بهوسیلهٔ اتحاد مشتق میشوند مجاز هستند.</translation> + </message> + <message> + <source>%1 contains %2 facet with invalid data: %3.</source> + <translation>%1 شامل رویهٔ %2 با دادهٔ نامعتبر است: %3.</translation> + </message> + <message> + <source>Attribute group %1 contains attribute %2 twice.</source> + <translation>گروه صفت %1 صفت %2 را دوبار شامل است.</translation> + </message> + <message> + <source>Attribute group %1 contains two different attributes that both have types derived from %2.</source> + <translation>گروه صفت %1 شامل دو صفت متفاوت است که هر دو از %2 مشتق شدهاند.</translation> + </message> + <message> + <source>Attribute group %1 contains attribute %2 that has value constraint but type that inherits from %3.</source> + <translation>گروه صفت %1 شامل صفت %2 است.که قید مقدار دارد اما نوع را از %3 به ارث میبرد.</translation> + </message> + <message> + <source>Complex type %1 contains attribute %2 twice.</source> + <translation>نوع پیچیدهٔ %1 صفت %2 را دوبار شامل است.</translation> + </message> + <message> + <source>Complex type %1 contains two different attributes that both have types derived from %2.</source> + <translation>نوع پیچیدهٔ %1 شامل دو صفت متفاوت است که هر دو از %2 مشتق شدهاند.</translation> + </message> + <message> + <source>Complex type %1 contains attribute %2 that has value constraint but type that inherits from %3.</source> + <translation>نوع پیچیدهٔ %1 شامل صفت %2 است.که قید مقدار دارد اما نوع را از %3 به ارث میبرد.</translation> + </message> + <message> + <source>Element %1 is not allowed to have a value constraint if its base type is complex.</source> + <translation>نوع %1 مجاز به داشتن قید مقدار نیست اگر نوع پایهاش پیچیده باشد.</translation> + </message> + <message> + <source>Element %1 is not allowed to have a value constraint if its type is derived from %2.</source> + <translation>نوع %1 مجاز به داشتن قید مقدار نیست اگر از %2 مشتق شود.</translation> + </message> + <message> + <source>Value constraint of element %1 is not of elements type: %2.</source> + <translation>قید مقدار عنصر %1 از نوع عنصر نیست: %2.</translation> + </message> + <message> + <source>Element %1 is not allowed to have substitution group affiliation as it is no global element.</source> + <translation>نوع %1 مجاز به داشتن وابستگی مجموعهٔ زیرحالت نیست مادامی که عنصر سراسری نباشد.</translation> + </message> + <message> + <source>Type of element %1 cannot be derived from type of substitution group affiliation.</source> + <translation>نوع عنصر %1 نمیتواند از نوع وابستگی مجموعهٔ زیرحالت مشتق شود.</translation> + </message> + <message> + <source>Value constraint of attribute %1 is not of attributes type: %2.</source> + <translation>مقدار قید صفت %1 نوع صفت نیست: %2.</translation> + </message> + <message> + <source>Attribute %1 has value constraint but has type derived from %2.</source> + <translation>صفت %1 مقدار قید دارد اما از نوع %2 مشتق شده است.</translation> + </message> + <message> + <source>%1 attribute in derived complex type must be %2 like in base type.</source> + <translation>%1 صفت در نوع پیچیدهٔ مشتق شده باید مانند %2 در نوع پایه باشد.</translation> + </message> + <message> + <source>Attribute %1 in derived complex type must have %2 value constraint like in base type.</source> + <translation>%1 صفت در نوع پیچیدهٔ مشتق شده باید %2 مانند نوع پایه باشد.</translation> + </message> + <message> + <source>Attribute %1 in derived complex type must have the same %2 value constraint like in base type.</source> + <translation>صفت %1 در نوع پیچیدهٔ مشتق شده باید همان %2 قید مقدار را مانند نوع پایه داشته باشد.</translation> + </message> + <message> + <source>Attribute %1 in derived complex type must have %2 value constraint.</source> + <translation>صفت %1 در نوع پیچیدهٔ مشتق شده باید %2 قید مقدار داشته باشد.</translation> + </message> + <message> + <source>processContent of base wildcard must be weaker than derived wildcard.</source> + <translation>محتویات پردازش در حروف جایگزین شونده پایه باید از حروف جایگزین شوندهٔ مشتق شده ضعیفتر باشند.</translation> + </message> + <message> + <source>Element %1 exists twice with different types.</source> + <translation>عنصر %1 دوبار با انواع متفاوت وجود دارد.</translation> + </message> + <message> + <source>Particle contains non-deterministic wildcards.</source> + <translation>ذره شامل حروف جایگزین شوندهٔ قطعی نیست.</translation> + </message> + <message> + <source>Base attribute %1 is required but derived attribute is not.</source> + <translation>صفت پایهٔ %1 مورد نیاز است اما صفت مشتق شده نه.</translation> + </message> + <message> + <source>Type of derived attribute %1 cannot be validly derived from type of base attribute.</source> + <translation>نوع صفت مشتق شدهٔ %1 نمیتواند به طور معتبر از صفت پایه مشتق شود.</translation> + </message> + <message> + <source>Value constraint of derived attribute %1 does not match value constraint of base attribute.</source> + <translation>قید مقدار صفت مشتق شدهٔ %1 با قید مقدار صفت پایه مطابق نیست.</translation> + </message> + <message> + <source>Derived attribute %1 does not exist in the base definition.</source> + <translation>صفت مشتق شدهٔ %1 در تعریف پایه وجود ندارد.</translation> + </message> + <message> + <source>Derived attribute %1 does not match the wildcard in the base definition.</source> + <translation>صفت مشتق شدهٔ %1 با کلمات جایگزین شونده در تعریف پایه مطابقت ندارد.</translation> + </message> + <message> + <source>Base attribute %1 is required but missing in derived definition.</source> + <translation>صفت پایهٔ %1 مورد نیاز است اما صفت مشتق شده مفقود شده است.</translation> + </message> + <message> + <source>Derived definition contains an %1 element that does not exists in the base definition</source> + <translation>تعریف مشتق شده شامل صفت %1 است که در تعریف پایه وجود ندارد</translation> + </message> + <message> + <source>Derived wildcard is not a subset of the base wildcard.</source> + <translation>حروف جایگزین شوندهٔ مشتق شده زیر مجموعهای از حروف جایگزین شوندهٔ پایه نیستند.</translation> + </message> + <message> + <source>%1 of derived wildcard is not a valid restriction of %2 of base wildcard</source> + <translation>%1 حروف جایگزین شونده مشتق شده، قید معتبر %2 حروف جایگزین شوندهٔ پایه نیستند</translation> + </message> + <message> + <source>Attribute %1 from base type is missing in derived type.</source> + <translation>صفت %1 از نوع پایه در نوع مشتق شده مفقود شده است.</translation> + </message> + <message> + <source>Type of derived attribute %1 differs from type of base attribute.</source> + <translation>نوع صفت مشتق شده %1 از نوع صفت پایه متفاوت است.</translation> + </message> + <message> + <source>Base definition contains an %1 element that is missing in the derived definition</source> + <translation>تعریف پایه شامل عنصر %1 است که در تعریف مشتق شده مفقود شده است</translation> + </message> + <message> + <source>Can not process unknown element %1, expected elements are: %2.</source> + <translation>نمیتوان عنصر ناشناختهٔ %1 را پردازش کرد، عناصر مورد انتظار اینها هستند: %2.</translation> + </message> + <message> + <source>Element %1 is not allowed in this scope, possible elements are: %2.</source> + <translation>عنصر %1 در این قلمرو مجاز نیست، عناصر ممکن اینها هستند: %2.</translation> + </message> + <message> + <source>Child element is missing in that scope, possible child elements are: %1.</source> + <translation>عنصر فرزند در این قلمرو مفقود شده است، عناصر فرزند ممکن اینها هستند: %1.</translation> + </message> + <message> + <source>Document is not a XML schema.</source> + <translation>سند یک الگوی XML نیست.</translation> + </message> + <message> + <source>%1 attribute of %2 element contains invalid content: {%3} is not a value of type %4.</source> + <translation>صفت %1 از عنصر %2 شامل محتویات غیرمجاز است: {%3} یک مقدار از نوع %4 نیست.</translation> + </message> + <message> + <source>%1 attribute of %2 element contains invalid content: {%3}.</source> + <translation>صفت %1 از عنصر %2 شامل محتویات غیرمجاز است: {%3}.</translation> + </message> + <message> + <source>Target namespace %1 of included schema is different from the target namespace %2 as defined by the including schema.</source> + <translation>فضاینامی هدف %1 طرح شامل شده متفاوت از فضاینامی هدف %2 آنگونه که به وسلیهٔ طرح شامل تعریف شده است میباشد.</translation> + </message> + <message> + <source>Target namespace %1 of imported schema is different from the target namespace %2 as defined by the importing schema.</source> + <translation>فضاینامی %1 طرح وارد شده متفاوت از فضاینامی هدف %2 آنگونه که به وسلیهٔ طرح وارد شده تعریف شده است میباشد.</translation> + </message> + <message> + <source>%1 element is not allowed to have the same %2 attribute value as the target namespace %3.</source> + <translation>عنصر %1 مجاز نیست که صفت %2 ی یکسان بافضاینام هدف %3 داشته باشد.</translation> + </message> + <message> + <source>%1 element without %2 attribute is not allowed inside schema without target namespace.</source> + <translation>عنصر %1 بدون صفت %2 در طرح بدون فضاینامی هدف مجاز نیست.</translation> + </message> + <message> + <source>%1 element is not allowed inside %2 element if %3 attribute is present.</source> + <translation>عنصر %1 در عنصر %2 اگر صفت %3 ارائه شده باشد مجاز نیست.</translation> + </message> + <message> + <source>%1 element has neither %2 attribute nor %3 child element.</source> + <translation>عنصر %1 نه صفت %2 را دارد نه عنصر فرزند %3 را دارد.</translation> + </message> + <message> + <source>%1 element with %2 child element must not have a %3 attribute.</source> + <translation>عنصر %1 با فرزند %2 نباید صفت %3 را داشته باشد.</translation> + </message> + <message> + <source>%1 attribute of %2 element must be %3 or %4.</source> + <translation>صفت %1 از عنصر %2 باید %3 یا %4 باشد.</translation> + </message> + <message> + <source>%1 attribute of %2 element must have a value of %3.</source> + <translation>صفت %1 از عنصر %2 باید مقدار %3 را داشته باشد.</translation> + </message> + <message> + <source>%1 attribute of %2 element must have a value of %3 or %4.</source> + <translation>صفت %1 از عنصر %2 باید مقدار %3 یا %4 را داشته باشد.</translation> + </message> + <message> + <source>%1 element must not have %2 and %3 attribute together.</source> + <translation>عنصر %1 نباید صفات %2 و %3 را با هم داشته باشد.</translation> + </message> + <message> + <source>Content of %1 attribute of %2 element must not be from namespace %3.</source> + <translation>محتویات صفت %1 از عنصر %2 نباید از فضاینامی %3 باشد.</translation> + </message> + <message> + <source>%1 attribute of %2 element must not be %3.</source> + <translation>صفت %1 از عنصر %2 نباید %3 باشد.</translation> + </message> + <message> + <source>%1 attribute of %2 element must have the value %3 because the %4 attribute is set.</source> + <translation>صفت %1 از عنصر %2 باید مقدار %3 را داشته باشد زیرا صفت %4 تنظیم شده است.</translation> + </message> + <message> + <source>Specifying use='prohibited' inside an attribute group has no effect.</source> + <translation>تعیین استفاده = 'ممنوع' در گروه صفت هیچ تأثیری ندارد.</translation> + </message> + <message> + <source>%1 element must have either %2 or %3 attribute.</source> + <translation>عنصر %1 باید یکی از صفات %2 یا %3 را داشته باشد.</translation> + </message> + <message> + <source>%1 element must have either %2 attribute or %3 or %4 as child element.</source> + <translation>عنصر %1 باید صفت %2 یا %3 یا %4 را به عنوان فرزند داشته باشد.</translation> + </message> + <message> + <source>%1 element requires either %2 or %3 attribute.</source> + <translation>عنصر %1 یکی از صفات %2 یا %3 را نیاز دارد..</translation> + </message> + <message> + <source>Text or entity references not allowed inside %1 element</source> + <translation>ارجاع متن یا موجودیت در عنصر %1 مجاز نیست</translation> + </message> + <message> + <source>%1 attribute of %2 element must contain %3, %4 or a list of URIs.</source> + <translation>صفت %1 از عنصر %2 باید شامل %3، %4 یا لیستی از URLها باشد.</translation> + </message> + <message> + <source>%1 element is not allowed in this context.</source> + <translation>عنصر %1 در این زمینه مجاز نیست.</translation> + </message> + <message> + <source>%1 attribute of %2 element has larger value than %3 attribute.</source> + <translation>صفت %1 از عنصر %2 مقداری بزرگتر از صفت %3 دارد.</translation> + </message> + <message> + <source>Prefix of qualified name %1 is not defined.</source> + <translation>پیشوند نام دارای شرایط %1 تعریف نشده است.</translation> + </message> + <message> + <source>%1 attribute of %2 element must either contain %3 or the other values.</source> + <translation>صفت %1 از عنصر %2 باید شامل %3 یا مقادیر دیگری باشد.</translation> + </message> + <message> + <source>Component with ID %1 has been defined previously.</source> + <translation>جزئی با ID %1 قبلاً تعریف شده است.</translation> + </message> + <message> + <source>Element %1 already defined.</source> + <translation>عنصر %1 هماکنون تعریف شده است.</translation> + </message> + <message> + <source>Attribute %1 already defined.</source> + <translation>صفت %1 هماکنون تعریف شده است.</translation> + </message> + <message> + <source>Type %1 already defined.</source> + <translation>نوع %1 هماکنون تعریف شده است.</translation> + </message> + <message> + <source>Attribute group %1 already defined.</source> + <translation>گروه صفت %1 هماکنون تعریف شده است.</translation> + </message> + <message> + <source>Element group %1 already defined.</source> + <translation>گروه عنصر %1 هماکنون تعریف شده است.</translation> + </message> + <message> + <source>Notation %1 already defined.</source> + <translation>نشانهگذاری %1 هماکنون تعریف شده است.</translation> + </message> + <message> + <source>Identity constraint %1 already defined.</source> + <translation>قید هویت %1 هماکنون تعریف شده است.</translation> + </message> + <message> + <source>Duplicated facets in simple type %1.</source> + <translation>رویهٔ چندگانه در نوع سادهٔ %1.</translation> + </message> + <message> + <source>%1 references unknown %2 or %3 element %4.</source> + <translation>%1 %2 یا %3 نامشخص عنصر %4 مراجعه میکند.</translation> + </message> + <message> + <source>%1 references identity constraint %2 that is no %3 or %4 element.</source> + <translation>%1 به قید هویت %2 که عنصر %3 یا %4 نیست مراجعه میکند.</translation> + </message> + <message> + <source>%1 has a different number of fields from the identity constraint %2 that it references.</source> + <translation>%1 فیلد عددی متفاوتی از قید هویت %2 که به آن اشاره میکند دارد.</translation> + </message> + <message> + <source>Base type %1 of %2 element cannot be resolved.</source> + <translation>نمیتوان در مورد نوع پایهٔ %1 از عنصر %2 تصمیم گرفت.</translation> + </message> + <message> + <source>Item type %1 of %2 element cannot be resolved.</source> + <translation>نمیتوان در مورد آیتم نوع %1 از عنصر %2 تصمیم گرفت.</translation> + </message> + <message> + <source>Member type %1 of %2 element cannot be resolved.</source> + <translation>نمیتوان در مورد عضو نوع %1 از عنصر %2 تصمیم گرفت.</translation> + </message> + <message> + <source>Type %1 of %2 element cannot be resolved.</source> + <translation>نمیتوان در مورد نوع %1 از عنصر %2 تصمیم گرفت.</translation> + </message> + <message> + <source>Base type %1 of complex type cannot be resolved.</source> + <translation>نمیتوان در مورد نوع پایهٔ %1 از نوع پیچیده تصمیم گرفت.</translation> + </message> + <message> + <source>%1 cannot have complex base type that has a %2.</source> + <translation>%1 نمیتواند نوع پیچیدهٔ پایهای که یک %2 دارد داشته باشد.</translation> + </message> + <message> + <source>Content model of complex type %1 contains %2 element so it cannot be derived by extension from a non-empty type.</source> + <translation>محتویات مدل نوع پیچیدهٔ %1 شامل %2 است بنابراین نمیتواند با پسوند از نوع غیرتهی مشتق شود.</translation> + </message> + <message> + <source>Complex type %1 cannot be derived by extension from %2 as the latter contains %3 element in its content model.</source> + <translation>نوع پیچیدهٔ %1 نمیتواند با پسوند از %2 مشتق شود همچنان که اخیراً شامل عنصر %3 در مدل محتویاتش است.</translation> + </message> + <message> + <source>Type of %1 element must be a simple type, %2 is not.</source> + <translation>نوع عنصر %1 باید ساده باشد، در حالی که %2 نیست.</translation> + </message> + <message> + <source>Substitution group %1 of %2 element cannot be resolved.</source> + <translation>نمیتوان در مورد جانشینی گروه %1 از عنصر %2 تصمیم گرفت.</translation> + </message> + <message> + <source>Substitution group %1 has circular definition.</source> + <translation>جانشینی گروه %1 تعریف حلقوی دارد.</translation> + </message> + <message> + <source>Duplicated element names %1 in %2 element.</source> + <translation>نامهای چندگانهٔ %1 در عنصر %2.</translation> + </message> + <message> + <source>Reference %1 of %2 element cannot be resolved.</source> + <translation>نمیتوان در مورد ارجاع %1 از عنصر %2 تصمیم گرفت.</translation> + </message> + <message> + <source>Circular group reference for %1.</source> + <translation>ارجاع گروهی حلقوی برای %1.</translation> + </message> + <message> + <source>%1 element is not allowed in this scope</source> + <translation>عنصر %1 در این قلمرو مجاز نیست</translation> + </message> + <message> + <source>%1 element cannot have %2 attribute with value other than %3.</source> + <translation>عنصر %1 نمیتواند صفت %2 را با مقداری متفاوت از %3 داشته باشد.</translation> + </message> + <message> + <source>%1 element cannot have %2 attribute with value other than %3 or %4.</source> + <translation>عنصر %1 نمیتواند صفت %2 را با مقداری متفاوت از %3 یا %4 داشته باشد.</translation> + </message> + <message> + <source>%1 or %2 attribute of reference %3 does not match with the attribute declaration %4.</source> + <translation>صفت %1 یا %2 از ارجاع %3 با اعلان صفت %4 مطابق نیست.</translation> + </message> + <message> + <source>Attribute group %1 has circular reference.</source> + <translation>گروه صفت %1 ارجاع حلقوی دارد.</translation> + </message> + <message> + <source>%1 attribute in %2 must have %3 use like in base type %4.</source> + <translation>صفت %1 در %2 باید استفادهٔ %3 را مانند نوع پایهٔ %4 داشته باشد.</translation> + </message> + <message> + <source>Attribute wildcard of %1 is not a valid restriction of attribute wildcard of base type %2.</source> + <translation>صفت wildcard %1 قید معتبر صفت wildcard نوع پایهٔ %2 نیست.</translation> + </message> + <message> + <source>%1 has attribute wildcard but its base type %2 has not.</source> + <translation>%1 wildcard صفت دارد اما نوع پایهٔ %2 اش ندارد.</translation> + </message> + <message> + <source>Union of attribute wildcard of type %1 and attribute wildcard of its base type %2 is not expressible.</source> + <translation>اتحاد wildcars صفت نوع %1 و wildcard صفت نوع پایهٔ %2 آن قابل بیان نیست.</translation> + </message> + <message> + <source>Enumeration facet contains invalid content: {%1} is not a value of type %2.</source> + <translation>رویهٔ شمارش شامل محتویات غیر مجاز است: {%1} یک مقدار از نوع %2 نیست.</translation> + </message> + <message> + <source>Namespace prefix of qualified name %1 is not defined.</source> + <translation>پیشوند فضاینامی نام مشخص شدهٔ %1 تعریف نشده است.</translation> + </message> + <message> + <source>%1 element %2 is not a valid restriction of the %3 element it redefines: %4.</source> + <translation>%1 عنصر %2 یک قید معتبر عنصر %3 که %4 را بازتعریف میکند نیست.</translation> + </message> + <message> + <source>%1 is not valid according to %2.</source> + <translation>%1 بر طبق %2 معتبر نیست.</translation> + </message> + <message> + <source>String content does not match the length facet.</source> + <translation>محتوای رشته با رویهٔ طول مطابق نیست.</translation> + </message> + <message> + <source>String content does not match the minLength facet.</source> + <translation>محتوای رشته با رویهٔ طول مینیمم مطابق نیست.</translation> + </message> + <message> + <source>String content does not match the maxLength facet.</source> + <translation>محتوای رشته با رویهٔ طول ماکزیمم مطابق نیست.</translation> + </message> + <message> + <source>String content does not match pattern facet.</source> + <translation>محتوای رشته با رویهٔ الگو مطابق نیست.</translation> + </message> + <message> + <source>String content is not listed in the enumeration facet.</source> + <translation>محتوای رشته در رویهٔ شمارش لیست نشده.</translation> + </message> + <message> + <source>Signed integer content does not match the maxInclusive facet.</source> + <translation>محتوای عدد صحیح علامتدار با رویهٔ شامل ماکزیمم مطابق نیست.</translation> + </message> + <message> + <source>Signed integer content does not match the maxExclusive facet.</source> + <translation>محتوای عدد صحیح علامتدار با رویهٔ فقط ماکزیمم مطابق نیست.</translation> + </message> + <message> + <source>Signed integer content does not match the minInclusive facet.</source> + <translation>محتوای عدد صحیح علامتدار با رویهٔ شامل مینیمم مطابق نیست.</translation> + </message> + <message> + <source>Signed integer content does not match the minExclusive facet.</source> + <translation>محتوای عدد صحیح علامتدار با رویهٔ فقط مینیمم مطابق نیست.</translation> + </message> + <message> + <source>Signed integer content is not listed in the enumeration facet.</source> + <translation>محتوای عدد صحیح علامتدار در رویهٔ شمارش لیست نشده.</translation> + </message> + <message> + <source>Signed integer content does not match pattern facet.</source> + <translation>محتوای عدد صحیح علامتدار با رویهٔ الگو مطابق نیست.</translation> + </message> + <message> + <source>Signed integer content does not match in the totalDigits facet.</source> + <translation>محتوای عدد صحیح علامتدار با رویهٔ مجموع ارقام مطابق نیست.</translation> + </message> + <message> + <source>Unsigned integer content does not match the maxInclusive facet.</source> + <translation>محتوای عدد صحیح بدون علامت با رویهٔ شامل ماکزیمم مطابق نیست.</translation> + </message> + <message> + <source>Unsigned integer content does not match the maxExclusive facet.</source> + <translation>محتوای عدد صحیح بدون علامت با رویهٔ فقط ماکزیمم مطابق نیست.</translation> + </message> + <message> + <source>Unsigned integer content does not match the minInclusive facet.</source> + <translation>محتوای عدد صحیح بدون علامت با رویهٔ شامل مینیمم مطابق نیست.</translation> + </message> + <message> + <source>Unsigned integer content does not match the minExclusive facet.</source> + <translation>محتوای عدد صحیح بدون علامت با رویهٔ فقط مینیمم مطابق نیست.</translation> + </message> + <message> + <source>Unsigned integer content is not listed in the enumeration facet.</source> + <translation>محتوای عدد صحیح بدون علامت در رویهٔ شمارش لیست نشده.</translation> + </message> + <message> + <source>Unsigned integer content does not match pattern facet.</source> + <translation>محتوای عدد صحیح بدون علامت با رویهٔ الگو مطابق نیست.</translation> + </message> + <message> + <source>Unsigned integer content does not match in the totalDigits facet.</source> + <translation>محتوای عدد صحیح بدون علامت با رویهٔ مجموع ارقام مطابق نیست.</translation> + </message> + <message> + <source>Double content does not match the maxInclusive facet.</source> + <translation>محتوای عدد اعشاری با رویهٔ شامل ماکزیمم مطابق نیست.</translation> + </message> + <message> + <source>Double content does not match the maxExclusive facet.</source> + <translation>محتوای عدد اعشاری با رویهٔ فقط ماکزیمم مطابق نیست.</translation> + </message> + <message> + <source>Double content does not match the minInclusive facet.</source> + <translation>محتوای عدد اعشاری با رویهٔ شامل مینیمم مطابق نیست.</translation> + </message> + <message> + <source>Double content does not match the minExclusive facet.</source> + <translation>محتوای عدد اعشاری با رویهٔ فقط مینیمم مطابق نیست.</translation> + </message> + <message> + <source>Double content is not listed in the enumeration facet.</source> + <translation>محتوای عدد اعشاری در رویهٔ شمارش لیست نشده.</translation> + </message> + <message> + <source>Double content does not match pattern facet.</source> + <translation>محتوای عدد اعشاری با رویهٔ الگو مطابق نیست.</translation> + </message> + <message> + <source>Decimal content does not match in the fractionDigits facet.</source> + <translation>محتوای عدد دهدهی با رویهٔ ارقام کسری مطابق نیست.</translation> + </message> + <message> + <source>Decimal content does not match in the totalDigits facet.</source> + <translation>محتوای عدد دهدهی با رویهٔ مجموع ارقام مطابق نیست.</translation> + </message> + <message> + <source>Date time content does not match the maxInclusive facet.</source> + <translation>محتوای تاریخ زمان با رویهٔ شامل ماکزیمم مطابق نیست.</translation> + </message> + <message> + <source>Date time content does not match the maxExclusive facet.</source> + <translation>محتوای تاریخ زمان با رویهٔ فقط ماکزیمم مطابق نیست.</translation> + </message> + <message> + <source>Date time content does not match the minInclusive facet.</source> + <translation>محتوای تاریخ زمان با رویهٔ شامل مینیمم مطابق نیست.</translation> + </message> + <message> + <source>Date time content does not match the minExclusive facet.</source> + <translation>محتوای تاریخ زمان با رویهٔ فقط مینیمم مطابق نیست.</translation> + </message> + <message> + <source>Date time content is not listed in the enumeration facet.</source> + <translation>محتوای تاریخ زمان در رویهٔ شمارش لیست نشده.</translation> + </message> + <message> + <source>Date time content does not match pattern facet.</source> + <translation>محتوای تاریخ زمان با رویهٔ الگو مطابق نیست.</translation> + </message> + <message> + <source>Duration content does not match the maxInclusive facet.</source> + <translation>محتوای مدت با رویهٔ شامل ماکزیمم مطابق نیست.</translation> + </message> + <message> + <source>Duration content does not match the maxExclusive facet.</source> + <translation>محتوای مدت با رویهٔ فقط ماکزیمم مطابق نیست.</translation> + </message> + <message> + <source>Duration content does not match the minInclusive facet.</source> + <translation>محتوای مدت با رویهٔ شامل مینیمم مطابق نیست.</translation> + </message> + <message> + <source>Duration content does not match the minExclusive facet.</source> + <translation>محتوای مدت با رویهٔ فقط مینیمم مطابق نیست.</translation> + </message> + <message> + <source>Duration content is not listed in the enumeration facet.</source> + <translation>محتوای مدت در رویهٔ شمارش لیست نشده.</translation> + </message> + <message> + <source>Duration content does not match pattern facet.</source> + <translation>محتوای مدت با رویهٔ الگو مطابق نیست.</translation> + </message> + <message> + <source>Boolean content does not match pattern facet.</source> + <translation>محتوای بولین با رویهٔ الگو مطابق نیست.</translation> + </message> + <message> + <source>Binary content does not match the length facet.</source> + <translation>محتوای دودویی با رویهٔ طول مطابق نیست.</translation> + </message> + <message> + <source>Binary content does not match the minLength facet.</source> + <translation>محتوای دودویی با رویهٔ طول مینیمم مطابق نیست.</translation> + </message> + <message> + <source>Binary content does not match the maxLength facet.</source> + <translation>محتوای دودویی با رویهٔ طول ماکزیمم مطابق نیست.</translation> + </message> + <message> + <source>Binary content is not listed in the enumeration facet.</source> + <translation>محتوای دودویی در رویهٔ شمارش لیست نشده.</translation> + </message> + <message> + <source>Invalid QName content: %1.</source> + <translation>محتوای نامعتبر QName: %1.</translation> + </message> + <message> + <source>QName content is not listed in the enumeration facet.</source> + <translation>محتوای QName در رویهٔ شمارش لیست نشده.</translation> + </message> + <message> + <source>QName content does not match pattern facet.</source> + <translation>محتوای QName با رویهٔ الگو مطابق نیست.</translation> + </message> + <message> + <source>Notation content is not listed in the enumeration facet.</source> + <translation>محتوای علامتگذاری در رویهٔ شمارش لیست نشده.</translation> + </message> + <message> + <source>List content does not match length facet.</source> + <translation>محتوای لیست با رویهٔ طول مطابق نیست.</translation> + </message> + <message> + <source>List content does not match minLength facet.</source> + <translation>محتوای لیست با رویهٔ طول مینیمم مطابق نیست.</translation> + </message> + <message> + <source>List content does not match maxLength facet.</source> + <translation>محتوای لیست با رویهٔ طول ماکزیمم مطابق نیست.</translation> + </message> + <message> + <source>List content is not listed in the enumeration facet.</source> + <translation>محتوای لیست در رویهٔ شمارش لیست نشده.</translation> + </message> + <message> + <source>List content does not match pattern facet.</source> + <translation>محتوای لیست با رویهٔ الگو مطابق نیست.</translation> + </message> + <message> + <source>Union content is not listed in the enumeration facet.</source> + <translation>محتوای اتحاد در رویهٔ شمارش لیست نشده.</translation> + </message> + <message> + <source>Union content does not match pattern facet.</source> + <translation>محتوای اتحاد با رویهٔ الگو مطابق نیست.</translation> + </message> + <message> + <source>Data of type %1 are not allowed to be empty.</source> + <translation>داده نوع %1 نمیتواند خالی باشد.</translation> + </message> + <message> + <source>Element %1 is missing child element.</source> + <translation>عنصر %1 عنصر فرزند را گم کرده است.</translation> + </message> + <message> + <source>There is one IDREF value with no corresponding ID: %1.</source> + <translation>هیچ IDREF ای با مقدار ID مترادف وجود ندارد: %1.</translation> + </message> + <message> + <source>Loaded schema file is invalid.</source> + <translation>فایل طرح بارشده نامعتبر است.</translation> + </message> + <message> + <source>%1 contains invalid data.</source> + <translation>%1 شامل دادهٔ نامعتبر است.</translation> + </message> + <message> + <source>xsi:schemaLocation namespace %1 has already appeared earlier in the instance document.</source> + <translation>فضاینامی xsi:chemalocation %1 هماکنون در ابتدای سند نمونه ظاهر شده.</translation> + </message> + <message> + <source>xsi:noNamespaceSchemaLocation cannot appear after the first no-namespace element or attribute.</source> + <translation>xsi:noNamespaceShemaLocation نمیتواند بعد از اولین عنصر یا صفت بدون فضاینامی ظاهر شود.</translation> + </message> + <message> + <source>No schema defined for validation.</source> + <translation>طرحی برای اعتبارسنجی تعریف نشده است.</translation> + </message> + <message> + <source>No definition for element %1 available.</source> + <translation>تعریفی برای عنصر %1 در دسترس نیست.</translation> + </message> + <message> + <source>Specified type %1 is not known to the schema.</source> + <translation>نوع مشخص شدهٔ %1 برای طرح ناشناخته است.</translation> + </message> + <message> + <source>Element %1 is not defined in this scope.</source> + <translation>عنصر %1 در این قلمرو تعریف نشده است.</translation> + </message> + <message> + <source>Declaration for element %1 does not exist.</source> + <translation>برای عنصر %1 اعلانی وجود ندارد.</translation> + </message> + <message> + <source>Element %1 contains invalid content.</source> + <translation>عنصر %1 شامل محتوای نامعتبر است.</translation> + </message> + <message> + <source>Element %1 is declared as abstract.</source> + <translation>عنصر %1 به صورت انتزاعی اعلان است.</translation> + </message> + <message> + <source>Element %1 is not nillable.</source> + <translation>عنصر %1 nillable نیست.</translation> + </message> + <message> + <source>Attribute %1 contains invalid data: %2</source> + <translation>صفت %1 شامل دادهٔ نامعتبر است: %2</translation> + </message> + <message> + <source>Element contains content although it is nillable.</source> + <translation>عنصر شامل محتویاتی است اگرچه nillable است.</translation> + </message> + <message> + <source>Fixed value constraint not allowed if element is nillable.</source> + <translation>قید عنصر ثابت مجاز نیست اگر عنصر nillable باشد.</translation> + </message> + <message> + <source>Specified type %1 is not validly substitutable with element type %2.</source> + <translation>عنصر مشخص شده نوع %1 نمیتواند به طور معتبر با عنصر نوع %2 جایگزین شود.</translation> + </message> + <message> + <source>Complex type %1 is not allowed to be abstract.</source> + <translation>نوع پیچیدهٔ %1 نمیتواند انتزاعی باشد.</translation> + </message> + <message> + <source>Element %1 contains not allowed attributes.</source> + <translation>عنصر %1 شامل صفت غیرمجاز است.</translation> + </message> + <message> + <source>Element %1 contains not allowed child element.</source> + <translation>عنصر %1 شامل عنصر فرزند غیرمجاز است.</translation> + </message> + <message> + <source>Content of element %1 does not match its type definition: %2.</source> + <translation>محتویات عنصر %1 با تعریفش مطابق نیست: %2.</translation> + </message> + <message> + <source>Content of element %1 does not match defined value constraint.</source> + <translation>محتویات عنصر %1 با قید مقدار تعریف شده مطابق نیست.</translation> + </message> + <message> + <source>Element %1 contains not allowed child content.</source> + <translation>عنصر %1 شامل محتویات فرزند غیرمجاز است.</translation> + </message> + <message> + <source>Element %1 contains not allowed text content.</source> + <translation>عنصر %1 شامل محتویات متن غیرمجاز است.</translation> + </message> + <message> + <source>Element %1 cannot contain other elements, as it has a fixed content.</source> + <translation>اگر عنصر %1 ثابت باشد نمیتواند شامل عناصر دیگر باشد.</translation> + </message> + <message> + <source>Element %1 is missing required attribute %2.</source> + <translation>عنصر %1 صفت گمشدهٔ موردنیاز %2 است.</translation> + </message> + <message> + <source>Attribute %1 does not match the attribute wildcard.</source> + <translation>صفت %1 با کاراکتر جایگزین شونده مطابق نیست.</translation> + </message> + <message> + <source>Declaration for attribute %1 does not exist.</source> + <translation>برای صفت %1 اعلانی وجود ندارد.</translation> + </message> + <message> + <source>Element %1 contains two attributes of type %2.</source> + <translation>عنصر %1 دو صفت از نوع %2 دارد.</translation> + </message> + <message> + <source>Attribute %1 contains invalid content.</source> + <translation>صفت %1 شامل محتویات نامعتبر است.</translation> + </message> + <message> + <source>Element %1 contains unknown attribute %2.</source> + <translation>عنصر %1 شامل صفت ناشناختهٔ %2 است.</translation> + </message> + <message> + <source>Content of attribute %1 does not match its type definition: %2.</source> + <translation>محتویات صفت %1 با تعریف نوعش مطابق نیست: %2.</translation> + </message> + <message> + <source>Content of attribute %1 does not match defined value constraint.</source> + <translation>محتویات صفت %1 با قید مقدار تعریف شده مطابق نیست.</translation> + </message> + <message> + <source>Non-unique value found for constraint %1.</source> + <translation>مقدار غیر یکتا برای قید %1 پیدا شد.</translation> + </message> + <message> + <source>Key constraint %1 contains absent fields.</source> + <translation>قید کلید %1 شامل فیلد مفقود است.</translation> + </message> + <message> + <source>Key constraint %1 contains references nillable element %2.</source> + <translation>قید کلید %1 شامل ارجاعهای عنصر nillable %2 است.</translation> + </message> + <message> + <source>No referenced value found for key reference %1.</source> + <translation>هیچ عنصر مراجعه شدهای برای کلید مرجع %1 پیدا نشد.</translation> + </message> + <message> + <source>More than one value found for field %1.</source> + <translation>بیش از یک مقدار برای میدان %1 پیدا شد.</translation> + </message> + <message> + <source>Field %1 has no simple type.</source> + <translation>فیلد %1 نوع سادهای ندارد.</translation> + </message> + <message> + <source>ID value '%1' is not unique.</source> + <translation>مقدار ID «%1» یکتا نیست.</translation> + </message> + <message> + <source>'%1' attribute contains invalid QName content: %2.</source> + <translation>صفت «%1» شامل محتوای نامعتبر QName است: %2.</translation> + </message> + <message> + <source>empty</source> + <translation>خالی</translation> + </message> + <message> + <source>zero or one</source> + <translation>صفر یا یک</translation> + </message> + <message> + <source>exactly one</source> + <translation>دقیقاً یک</translation> + </message> + <message> + <source>one or more</source> + <translation>یک یا بیشتر</translation> + </message> + <message> + <source>zero or more</source> + <translation>صفر یا بیشتر</translation> + </message> + <message> + <source>Required type is %1, but %2 was found.</source> + <translation>نوع درخواستی %1 است اما %2 پیدا شد.</translation> + </message> + <message> + <source>Promoting %1 to %2 may cause loss of precision.</source> + <translation>بالا بردن %1 نسبت به %2 ممکن است باعث ازدسترفتن دقت شود.</translation> + </message> + <message> + <source>The focus is undefined.</source> + <translation>کانون تعریف نشده است.</translation> + </message> + <message> + <source>It's not possible to add attributes after any other kind of node.</source> + <translation>بعد از هر نوع گره امکان اضافهکردن صفت وجود ندارد.</translation> + </message> + <message> + <source>An attribute by name %1 has already been created.</source> + <translation>یک صفت با نام %1 هماکنون ساخته شده است.</translation> + </message> + <message> + <source>Only the Unicode Codepoint Collation is supported(%1). %2 is unsupported.</source> + <translation>فقط تطبیق کد یونیکد پشتیبانی شده است (%1). %2 پشتیبانی نشده است.</translation> + </message> +</context> +</TS> |